diff --git a/src/form.rs b/src/form.rs index 2b05f48..be4c5f9 100644 --- a/src/form.rs +++ b/src/form.rs @@ -87,8 +87,10 @@ struct FullFormBuilder { fd: RwSignal, fs: FS, validations: Vec>>, - validation_cbs: Vec>, - views: Vec, + render_fns: + Vec) -> (View, Option>) + 'static>>, + // validation_cbs: Vec>, + // views: Vec, } /// The internal type for building forms @@ -126,8 +128,9 @@ impl FormBuilder { fd, fs: form_style, validations: Vec::new(), - validation_cbs: Vec::new(), - views: Vec::new(), + render_fns: Vec::new(), + // validation_cbs: Vec::new(), + // views: Vec::new(), }), } } @@ -168,8 +171,12 @@ impl FormBuilder { }; let render_data = vanity_control.build(); - let view = VanityControlData::build_control(&builder.fs, render_data); - builder.views.push(view); + let render_fn = move |fs: &FS, _| { + let view = VanityControlData::build_control(fs, render_data); + (view, None) + }; + + builder.render_fns.push(Box::new(render_fn)); } fn add_control( @@ -203,31 +210,36 @@ impl FormBuilder { builder.validations.push(validation_fn.clone()); } - let (validation_cb, view) = Self::build_control_view( - builder, - getter, - setter, - unparse_fn, - parse_fn, - validation_fn, - render_data, - ); + let render_fn = move |fs: &FS, fd: RwSignal| { + let (view, cb) = Self::build_control_view( + fd, + fs, + getter, + setter, + unparse_fn, + parse_fn, + validation_fn, + render_data, + ); + (view, Some(cb)) + }; - builder.views.push(view); - builder.validation_cbs.push(validation_cb); + // builder.views.push(view); + // builder.validation_cbs.push(validation_cb); + builder.render_fns.push(Box::new(render_fn)); } fn build_control_view( - builder: &FullFormBuilder, + fd: RwSignal, + fs: &FS, getter: Rc>, setter: Rc>, unparse_fn: Box::ReturnType, FDT>>, parse_fn: Box::ReturnType, FDT>>, validation_fn: Option>>, render_data: crate::controls::ControlRenderData, - ) -> (Box, View) { + ) -> (View, Box) { let (validation_signal, validation_signal_set) = create_signal(Ok(())); - let fd = builder.fd; let value_getter = move || { let getter = getter.clone(); // memoize so that updating one field doesn't cause a re-render for all fields @@ -275,13 +287,13 @@ impl FormBuilder { let value_setter = Box::new(value_setter); let view = C::build_control( - &builder.fs, + fs, render_data, value_getter, value_setter, validation_signal.into(), ); - (validation_cb, view) + (view, validation_cb) } fn build_action_form( @@ -298,12 +310,17 @@ impl FormBuilder { FormBuilderInner::ValidationBuilder { validations: _ } => return None, }; - let elements = builder.fs.form_frame(builder.views.into_view()); + let (views, validation_cbs): (Vec<_>, Vec<_>) = builder + .render_fns + .into_iter() + .map(|r_fn| r_fn(&builder.fs, builder.fd)) + .unzip(); + + let elements = builder.fs.form_frame(views.into_view()); - let validation_cbs = builder.validation_cbs; let on_submit = move |ev: SubmitEvent| { let mut failed = false; - for validation in validation_cbs.iter() { + for validation in validation_cbs.iter().flatten() { if !validation() { failed = true; } @@ -332,12 +349,17 @@ impl FormBuilder { FormBuilderInner::ValidationBuilder { validations: _ } => return None, }; - let elements = builder.fs.form_frame(builder.views.into_view()); + let (views, validation_cbs): (Vec<_>, Vec<_>) = builder + .render_fns + .into_iter() + .map(|r_fn| r_fn(&builder.fs, builder.fd)) + .unzip(); + + let elements = builder.fs.form_frame(views.into_view()); - let validation_cbs = builder.validation_cbs; let on_submit = move |ev: SubmitEvent| { let mut failed = false; - for validation in validation_cbs.iter() { + for validation in validation_cbs.iter().flatten() { if !validation() { failed = true; }