The field does not exists in the Schema of form,
i am using ionic template in form, this code does not work to me:
Template.example.helpers({
cardOptions: [
{ value: 0, label:'Visa' },
{ value: 1, label:'MasterCard' },
{ value: 2, label:'Elo' },
{ value: 3, label:'Hipercard' },
{ value: 4, label:'Hiper' }
]
});
<template name="example">
{{> afQuickField name="payment.card" type="select-radio" options=cardOptions }}
</template>
You need to use the autoForm component if you want to define fields individually.
For example:
<template name="example">
{{#autoForm collection="Payments" id="insertPaymentForm" type="insert"}}
<fieldset>
<legend>Add a Payment Method</legend>
{{> afQuickField name='title'}}
{{> afQuickField name="card" type="select-radio" options=cardOptions }}
</fieldset>
<button type="submit" class="btn btn-primary">Insert</button>
{{/autoForm}}
</template>
Here is a MeteorPad.
I'm trying to create a form in order to insert a new element inside a nested array in a collection.
Here are my schemas :
Schemas.CampaignsSchema = new SimpleSchema({
'name': {
type: String
}
});
Schemas.ElectionsSchema = new SimpleSchema({
'campaigns': {
type: [Schemas.CampaignsSchema],
defaultValue: []
}
});
Here is my template :
Template.campaignsNew.helpers({
schema() { return Schemas.CampaignsSchema; },
});
<template name="campaignsNew">
{{#autoForm
collection='Elections'
schema=schema
doc=doc
scope='campaigns'
id='insertCampaignForm'
type='update-pushArray'}}
<fieldset>
<legend>Add a Campaign</legend>
{{> afQuickField name='campaigns.$.name'}}
</fieldset>
<button type="submit" class="btn btn-primary">Insert</button>
{{/autoForm}}
</template>
So a field is generated by autoform but nothing happens when I hit submit.
If I enable Autoform.debug() I got :
SimpleSchema.clean: filtered out value that would have affected key "campaigns", which is not allowed by the schema
SimpleSchema.clean: filtered out value that would have affected key "campaigns.$", which is not allowed by the schema
SimpleSchema.clean: filtered out value that would have affected key "campaigns.$.name", which is not allowed by the schema
Does someone have any idea?
It seems that the schema attribute of #autoform doesn't work with the type update-pushArray.
Here is the template that works with the reste of the code :
<template name="campaignsNew">
{{#autoForm
collection='Elections'
doc=election
id='insertCampaignForm'
type='update-pushArray'
scope='campaigns'}}
<fieldset>
<legend>Add a Campaign</legend>
{{> afQuickField name='name'}}
</fieldset>
<button type="submit" class="btn btn-primary">Insert</button>
{{/autoForm}}
</template>
The only issue is that the name field is pre-filled with the Election name...
It seems that your nested document mustn't have a field with the same name as the main document.
Yet the created nested document has the good name and the main document's name remain unchanged.
I'm trying to make some helpers in the template where my AutoForm form lives to change some elements out side of the form to reflect errors. I've tried using
Template.signUp.helpers
isValid: ->
AutoForm.getValidationContext('signUp').isValid()
But that just returns the following error:
Exception in template helper: TypeError: Cannot read property '_resolvedSchema' of undefined
Here's the template:
<template name="signUp">
{{#if isValid}} do something {{/if}}
{{#autoForm id="signUp" schema="Schemas.SignUp" type="normal"}}
<div class="input {{#if afFieldIsInvalid name='firstName'}}error{{/if}}">
<label for="firstName">{{data.firstName}}</label>
{{> afFieldInput name="firstName" type="text"}}
</div>
<div class="input {{#if afFieldIsInvalid name='lastName'}}error{{/if}}">
<label for="lastName">{{data.lastName}}</label>
{{> afFieldInput name="lastName" type="text"}}
</div>
<div class="input {{#if afFieldIsInvalid name='email'}}error{{/if}}">
<label for="email">{{data.email}}</label>
{{> afFieldInput name="email" type="email"}}
</div>
<div class="input">
{{> afFieldInput name="optIn" type="boolean-checkbox"}}
</div>
<button type="submit" class="btn full" data-analytics='{"eventCategory":"Sign Up","eventAction":"Click","eventLabel":"{{data.submit}}"}'><span>{{data.submit}}</span></button>
{{/autoForm}}
</div>
</div>
Any help is greatly appreciated, thanks!
****UPDATE – Found Solution****
So after lots of playing I discovered that when you're trying to validate an AutoForm outside of the AutoForm context, you should use SimpleSchema to validate.
Here's where I'm defining the schema and saving the named context (coffeescript)
#Schemas = {}
#Schemas.SignUp = new SimpleSchema
firstName:
type: String
optional: false
lastName:
type: String
optional: false
email:
type: String
regEx: SimpleSchema.RegEx.Email
optional: false
optIn:
type: Boolean
label: Localization.signUp.optIn
optional: true
defaultValue: false
#SignUpForm = Schemas.SignUp.namedContext('signUp')
And here is where I'm using SimpleSchema to validate the entire form.
Template.signUp.helpers
isValid: ->
SignUpForm.isValid()
sds
I have this Schema :
Schemas = {};
Schemas.Id = {
type: String,
optional: true,
label: 'Id',
//max: ID_LENGTH,
defaultValue : Random.id(ID_LENGTH),
denyUpdate: true
};
Schemas.Name = {
type: String,
label: 'Name',
max: 75
};
Schemas.Description = {
type: String,
label: 'Description',
max: 500,
optional: true,
autoform: {
rows: 5
}
};
//-- Attribute
Schemas.Attribute = {
_id: Schemas.Id,
attribute_name : Schemas.Name,
attribute_description : Schemas.Description
};
Collections.Attributes.attachSchema(Schemas.Attribute);
i have a request from client they can insert _id manually.
but autoform cant permit it,
this the template :
<template name="pg_attr_insert">
{{#autoForm _id="afInsertDemo" type="insert" collection=Collections.Attributes}}
<div class="form-group {{#if afFieldIsInvalid name='_id'}}has-error{{/if}}">
<label class="control-label">{{afFieldLabelText name='_id'}}</label>
{{> afFieldInput name='_id'}}
{{#if afFieldIsInvalid name='_id'}}
<span class="help-block">{{{afFieldMessattribute_description name='_id'}}}</span>
{{/if}}
</div>
<div class="form-group {{#if afFieldIsInvalid name='attribute_name'}}has-error{{/if}}">
<label class="control-label">{{afFieldLabelText name='attribute_name'}}</label>
{{> afFieldInput name='attribute_name'}}
{{#if afFieldIsInvalid name='attribute_name'}}
<span class="help-block">{{{afFieldMessattribute_description name='attribute_name'}}}</span>
{{/if}}
</div>
<div class="form-group {{#if afFieldIsInvalid name='attribute_description'}}has-error{{/if}}">
<label class="control-label">{{afFieldLabelText name='attribute_description'}}</label>
{{> afFieldInput name='attribute_description'}}
{{#if afFieldIsInvalid name='attribute_description'}}
<span class="help-block">{{{afFieldMessattribute_description name='attribute_description'}}}</span>
{{/if}}
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Add Person</button>
<button type="reset" class="btn btn-default">Reset Form</button>
</div>
{{/autoForm}}
</template>
this is the error :
Uncaught Error: Every autoForm and quickForm must have an "id"
attribute set to a unique string.
is there anyway autoform permit insert _id manually? and how?
Oke i know my false, i create
{{#autoForm _id="afInsertDemo" type="insert" collection=Collections.Attributes}}
i just convert it to :
{{#autoForm id="afInsertDemo" type="insert" collection=Collections.Attributes}}
What is the best approach to dynamically show fields of a sub-schema (Object) depending on another field?
In the following example a document (Schemas.Main) can include several items defined in Schemas.Items. The fields that are needed to fill in items are dependendent on the selected type.
For example if a user selects type=="type1", fields "type1_field1" and "type1_field2" need to be filled.
A solution probably needs to use autoForm and combine AutoForm.getFieldValue and setting fields of an afArrayField, correct? I have tried a lot of combinations but either the ability to add additional items is lost (missing plus-sign) or I cannot add different items (i.e. all items are type1). Any hints 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}}
I finally used another approach and created an own template based on afArrayField, which uses
{{> UI.dynamic template=currentFieldValue}}
Not sure if this is the best approach but seems to be working 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>
Based on Miriam's answer, I would also like to share what i did to get things working. May be it could benifit.
Schemas -> 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",
}
});
Schemas -> 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%;"
}
}
});
Please note that Schemas.action1 should be loaded before Schemas.actions else you would only have a textbox rendered instead of the form
Templates
<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 would see {{> wizardButtons}} in the template which is because I am using the form-wizard package
and a Template.registerHelper for currentFieldValue helper
Template.registerHelper("currentFieldValue", function()
{
let val = AutoForm.getFieldValue(this.current.action_type, "actions-form");
return val || null;
});
Hope this helps some-one and saves time.
Thanks Mariam for this solution