Autoform: How to dynamically show and add subcircuit fields depending on another field?

What is the best approach to dynamically display fields of a subcircuit (object) depending on another field? In the following example, a document (Schemas.Main) may contain several elements defined in Schemas.Items. The fields required to fill in the elements depend on the selected type.

For example, if the user selects type == "type1", the fields "type1_field1" and "type1_field2" must be filled.

The solution should probably use autoForm and combine AutoForm.getFieldValue and set afArrayField fields, right? I tried many combinations, but either the ability to add additional elements is lost (there is no plus sign), or I can not add different elements (i.e. All elements are type1). Any clues how to solve this?

//Schemas.js Schemas = {}; Collections = {}; Main = Collections.Main = new Mongo.Collection("Main"); Main.attachSchema(Schemas.Main); Meteor.isClient && Template.registerHelper("Schemas", Schemas); Schemas.Main = new SimpleSchema({ name: { type: String }, items: { type: [Schemas.Items] } }); Schemas.Items = new SimpleSchema({ type: { //FormActions... type: String, allowedValues: ['type1', 'type2', 'type3'], autoform: { type: "selectize" } }, type1_field1: { type: String }, type1_field2: { type: String }, type2_field1: { type: String }, type2_field2: { type: String }, type3_field1: { type: String }, type3_field2: { type: String } }); //form.html {{#autoForm id="testForm" type="insert" collection=Collections.Main}} {{> afFieldInput name='name'}} {{> afArrayField name='items' fields="items.$.type, items.$.type1_field1"}} //How to set these fields dynamically depending on type? <div class="form-group"> <button type="submit" class="btn btn-primary">Create</button> </div> {{/autoForm}} 
+5
source share
2 answers

Finally, I took a different approach and created my own afArrayField-based template that uses

 {{> UI.dynamic template=currentFieldValue}} 

Not sure if this is the best approach, but seems to work for my situation:

 Template.registerHelper("currentFieldValue", function() { return AutoForm.getFieldValue("testForm", this.current.type) || "no type so far"; }); {{#autoForm id="testForm" type="insert" collection=Collections.Main}} {{> afFieldInput name='name'}} {{> afArrayField name='items' id="something" template="mycustom"}} <div class="form-group"> <button type="submit" class="btn btn-primary">Create</button> </div> {{/autoForm}} <template name="afArrayField_mycustom"> <div class="panel panel-default"> <div class="panel-heading">{{afFieldLabelText name=this.atts.name}}</div> {{#if afFieldIsInvalid name=this.atts.name}} <div class="panel-body has-error"> <span class="help-block">{{{afFieldMessage name=this.atts.name}}}</span> </div> {{/if}} <ul class="list-group"> {{#afEachArrayItem name=this.atts.name minCount=this.atts.minCount maxCount=this.atts.maxCount}} <li class="list-group-item autoform-array-item"> <div> <div class="autoform-remove-item-wrap"> {{#if afArrayFieldHasMoreThanMinimum name=../atts.name minCount=../atts.minCount maxCount=../atts.maxCount}} <button type="button" class="btn btn-primary autoform-remove-item"><span class="glyphicon glyphicon-minus"></span> </button> {{/if}} </div> <div class="autoform-array-item-body"> <!--all actions have a type --> {{> afFieldInput name=this.current.type label=false options="auto"}} <!--branch here for other fields that depend on type --> {{> UI.dynamic template=currentFieldValue}} </div> </div> </li> {{/afEachArrayItem}} {{#if afArrayFieldHasLessThanMaximum name=this.atts.name minCount=this.atts.minCount maxCount=this.atts.maxCount}} <li class="list-group-item"> <button type="button" class="btn btn-primary autoform-add-item" data-autoform-field="{{this.atts.name}}" data-autoform-minCount="{{this.atts.minCount}}" data-autoform-maxCount="{{this.atts.maxCount}}"><span class="glyphicon glyphicon-plus"></span> </button> </li> {{/if}} </ul> </div> </template> <template name="type1"> <!--include type1 fields here--> </template> <template name="type2"> <!--include type2 fields here--> </template> <template name="type3"> <!--include type3 fields here--> </template> 
+4
source

Based on Miriam's answer, I would also like to share what I did to make everything work. Maybe this can be helpful.

Schemes → Actions

 Schemas.actions = new SimpleSchema({ actions : { type : Array, optional: false, minCount: 1, autoform: { name: "actions" } }, "actions.$" : { type: Object }, "actions.$.action_type": { type : String, optional: false, label : "Action Type", autoform: { type : "select", class : "action_type form-control", name : "action_type", label : "Select type of action", options: function() { let returnValue = [ {label: "Action 1", value: "action_1"}, {label: "Action 2", value: "action_2"}, ]; return returnValue; } } }, "actions.$.action_1" : { type : Schemas.action1, minCount: 1, optional: true, label : "Action 1", } }); 

Schemes → action1

 Schemas.action1 = new SimpleSchema({ "action1_to" : { type : String, optional: false, label : "Email To", autoform: { type : "text", label : "Email To", placeholder: "Comma seperated values...", class : "form-control" } }, "action1_cc" : { type : String, optional: true, label : "Email Cc", autoform: { type : "text", label : "Email Cc", placeholder: "Comma seperated values...", class : "form-control" } }, "action1_subject": { type : String, optional: false, label : "Subject", autoform: { type : "text", label : "Subject", placeholder: "Subject for the Email", class : "form-control" } }, "action1_body" : { type : String, optional: false, label : "Email Content", autoform: { label : "Email Content", rows : 6, class : "form-control auto-size", placeholder: "Email Content goes here...", style : "font-size: 120%;" } } }); 

Note that Schemas.action1 must be loaded before Schemas.actions else, you will only have a text field instead of a form

Patterns

 <template name="actions"> {{#autoForm id="actions-form" doc=step.data schema=schema}} {{> afArrayField name="actions" template="actions" step=step}} {{> wizardButtons}} {{/autoForm}} </template> <template name="afArrayField_actions"> <div class="panel panel-default"> <div class="panel-heading">{{afFieldLabelText name=this.atts.name}}</div> {{#if afFieldIsInvalid name=this.atts.name}} <div class="panel-body has-error"> <span class="help-block">{{{afFieldMessage name=this.atts.name}}}</span> </div> {{/if}} <ul class="list-group"> {{#afEachArrayItem name=this.atts.name minCount=this.atts.minCount maxCount=this.atts.maxCount}} <li class="list-group-item autoform-array-item"> <div> <div class="autoform-remove-item-wrap"> {{#if afArrayFieldHasMoreThanMinimum name=../atts.name minCount=../atts.minCount maxCount=../atts.maxCount}} <button type="button" class="btn btn-primary autoform-remove-item"><span class="glyphicon glyphicon-minus"></span></button> {{/if}} </div> <div class="autoform-array-item-body"> {{> afQuickField name=this.current.action_type label=false options=actionOptions}} {{> UI.dynamic template=currentFieldValue data=this }} </div> </div> </li> {{/afEachArrayItem}} {{#if afArrayFieldHasLessThanMaximum name=this.atts.name minCount=this.atts.minCount maxCount=this.atts.maxCount}} <li class="list-group-item"> <button type="button" class="btn btn-primary autoform-add-item" data-autoform-field="{{this.atts.name}}" data-autoform-minCount="{{this.atts.minCount}}" data-autoform-maxCount="{{this.atts.maxCount}}"><span class="glyphicon glyphicon-plus"></span></button> </li> {{/if}} </ul> </div> </template> <template name="action_1"> {{> afQuickField name=this.current.action_1 }} </template> 

You will see {{> wizardButtons}} in the template because I use the form-wizard package

and Template.registerHelper for the currentFieldValue helper

 Template.registerHelper("currentFieldValue", function() { let val = AutoForm.getFieldValue(this.current.action_type, "actions-form"); return val || null; }); 

Hope this helps someone and saves time.

Thanks Mariam for this decision

-1
source

Source: https://habr.com/ru/post/1215166/


All Articles