I've the following (simplified) SimpleSchema:
EventSchema = new SimpleSchema({
eventType: {
type: String
},
kicker: {
type: String
},
kicker2: {
type: String,
optional: true
}
});
With this I'm using AutoForm to generate a insert form. Here is a simplified version of it:
{{#autoForm schema="EventSchema" type="method" meteormethod="addEvent"}}
{{> afFieldInput name="eventType" options=getSubstitutionEventTypes type="select-radio-inline"}}
{{> afFieldInput name="kicker" type="select" options=this}}
{{> afFieldInput name="kicker2" type="select" options=this}}
{{/autoForm}}
As I'm using this Schema in an other autoForm where I don't have to input "kicker2", I've set this field to be optional. But in the form mentioned above, this field is required too. So how can I override the optional setting for a field in a specific form?
I've already tried the following, but it didn't work (required isn't rendered in the HTML):
{{> afFieldInput name="kicker2" type="select" options=this required="required"}}
Thanks in advance!
You have some tricks to have an optional value depending on situations, a nice one would be to set the optional value on the return of a function, giving something like this:
EventSchema = new SimpleSchema({
eventType: {
type: String
},
kicker: {
type: String
},
kicker2: {
type: String,
optional: function() {
return (! this.isInsert)
}
}
});
So it is optional on update but not on insert (you can use whatever means to customize it).
Another way to have different validation rules between forms is simply by creating a specific schema for a given form and then having autoForm(schema=yourSpecificSchema ... instead of autoForm(collection="Meteor.users". Do not forget to register an helper so your schema is accessible from your form. You can refer on the official documentation for more details: https://github.com/aldeed/meteor-autoform#non-collection-forms
Related
Usually a regular person's name does not contain numbers, so I added this search property to prevent numbers with RegEx to my Input element:
type: new sap.ui.model.type.String({}, { search: "^[^0-9]+$" })
But numbers should be allowed for a company's name. So how can I make this search value dynamic?
To visualize it:
"dwd3" should be invalid when it's anything other than "Company"
"dwd3" should be valid when it's a "Company"
Here's my minimal example - what I've tried so far is commented out, since it didn't work (resulted in numbers being valid at all times).
// Set data model
let data = {
"salutation": "Company",
"name": ""
};
let oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
// Create page
let oPage = new sap.m.VBox();
oPage.setModel(oModel);
// Add salutation input
oPage.addItem(
new sap.m.Input({
value: {
path: "/salutation"
}
})
);
// Add name input
oPage.addItem(
new sap.m.Input({
value: {
type: new sap.ui.model.type.String({}, {
minLength: 2,
maxLength: 40,
search: "^[^0-9]+$"
/* not working...
search: {
parts: [
"/salutation",
],
formatter: (salutation) =>
salutation === "Company" ? "^.*$" : "^[^0-9]+$"
}
*/
}),
path: "/name",
},
required: true,
})
);
// Attach validation handlers
sap.ui.getCore().attachValidationError(function(oEvent) {
oEvent.getParameter("element").setValueState(sap.ui.core.ValueState.Error);
});
sap.ui.getCore().attachValidationSuccess(function(oEvent) {
oEvent.getParameter("element").setValueState(sap.ui.core.ValueState.None);
});
// Insert page
oPage.placeAt("content");
<script id='sap-ui-bootstrap' type='text/javascript' src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js' data-sap-ui-libs="sap.m,sap.ui.commons,sap.ui.table" data-sap-ui-theme="sap_bluecrystal">
</script>
<body class='sapUiBody'>
<div id='content'></div>
</body>
If the validation rule of one field depends on the value of another field, you could use events like change (with or without valueLiveUpdate=true) for validation.
A type should be something that does not depend on external life.
Another thing you could do is reacting on change event of your salutation field and exchange the type of the input field for the name (depending on the value of salutation)
PS: (edit) to be hontest, I wouldn't restrict a name field to anything that it may or may not contain. Depending on the country specific laws you may be allowed to use digits...
I am trying to implement a custom validation function which can return either true (if the field is valid) or some custom error message. Here's my current attempt:
global.Messages = Models.Messages = new Mongo.Collection 'messages'
MessagesSchema = new SimpleSchema({
content: {
type: String,
label: "Message",
max: 200,
custom: ->
if #obj.content.includes("a")
true
else
"not contain a"
}, {tracker: Tracker})
Messages.attachSchema MessagesSchema
This is a contrived example but still, it's not working. The conditional in the custom function is run, and when true gets returned then the record does save. However, if "not contain a" gets returned, it does not become the validation message displayed on the client. It just says content is invalid, and I'm not sure how to customize this message. Here's the template code:
{{#autoForm collection="Messages" id="insertMessageForm" type="insert"}}
<fieldset>
<legend>Add message</legend>
{{> afFieldInput type='text' name='content'}}
{{#if afFieldIsInvalid name='content'}}
<span class="help-block">{{afFieldMessage name='content'}}</span>
{{/if}}
</fieldset>
<button type='submit' class='btn btn-primary'>Insert</button>
{{/autoForm}}
There were a few problems with my original code.
First of all, I didn't specify how I was requiring SimpleSchema but it should be done this way; this uses the new node-simpl-schema package which is what meteor-simple-schema migrated to:
SimpleSchema = require('simpl-schema').default
SimpleSchema.extendOptions(['autoform']);
Validation messages are mapped to keys:
SimpleSchema.setDefaultMessages
messages:
en:
"notA": "doesnt contain a"
The messages and en hashes are necessary for it to be the correct structure.
important point: the return value of custom is not the message that gets displayed on the client. It is a key, pointing to the entry in the default messages object.
For example:
custom: ->
if #obj.content.includes("a")
true
else
"notA"
This will end up showing the message "doesnt contain a"
I am making a meteor web app where the user will click on a html button. Once this button is clicked, the user needs to be directed to another page with some forms generated by a meteor simple schema package. The first field in the simple schema needs to automatically be given a string value of "hello" and then the rest of the fields in the simple schema will be filled out by the user with the input fields on the page. What I am unsure about is how to get the first value automatically set to this string value. Here is some of the code I have:
The simple schema declaration:
LobbySchema = new SimpleSchema({
game: {
type: String,
label: "Game"
},
console: {
type: String,
label: "Console"
},
players: {
type: Number,
label: "Players"
},
mic: {
type: Boolean,
label: "Mic"
},
note: {
type: String,
label: "Note"
},
gamertag: {
type: String,
label: "Gamertag"
},
createdAt: {
type: Date,
label: "Created At",
autoValue: function(){
return new Date()
},
autoform: {
type: "hidden"
}
}
});
The first field there in the schema "game" needs to be given the value "hello" when the html button is clicked. Right now I can assign that value to a javascript variable using the button by having an onclick function:
function getElementText(elementID){
var elementText = "hello";
}
The button would call the getElementText function and have the elementText variable equal "hello". Now I need to assign the the first field in the simple schema to this variable value, "hello", then have it so the user can now fill out the rest of the schema with the input fields, automatically generated into the html with this code:
{{> quickForm collection="Lobby" id="insertLobbyForm" type="insert" class="newLobbyForm"}}
If you do not feel like providing the answer (maybe it happens to be more complicated than I think) then I would be very happy to receive a link to a site that might help me with this. I am also very willing to explain anything about the question if I did not explain the situation well enough above.
You can use the AutoForm hooks like this:
AutoForm.hooks({
app_create: {
before: {
method: function (doc) {
// Do whatever assignment you need to do here,
// like doc['game'] = "hello"; //then
return doc;
}
},
onSuccess: function (formType, result) {
},
onError: function (formType, error) {
}
}
});
Where here app_create is the id of the form you're sending with Autoform.
I'm currently trying to iterate through an array of Objects inside an Object.
I have my Collection "Proposals", and this is the corresponding Schema :
Schemas.ProposalsSchema = new SimpleSchema({
'content': {
type: String,
max: 140
},
'parties': {
type: [Object],
autoform : {
type: "select-multiple"
}
},
'parties.$._id': {
type: Object,
optional: true
},
'parties.$._id._str': {
type: String
},
'parties.$.name': {
type: String
}
});
I would like to iterate through the array of parties inside one of my template. I tried this :
{{#each proposals}}
<p>{{content}}</p>
<p>{{#each parties}} {{this.name}} {{/each}}</p>
{{/each}}
The content is displayed, but not the name of the different parties. Here's my template helper :
Template.proposalsIndex.helpers({
proposals: () => Proposals.find().fetch()
});
Do you know what do i do wrong?
Thank you in advance.
The code you posted looks ok.
Things you need to check are:
Is the "parties" field populated in a database? (you can run Proposals.find().fetch() in a meteor shell to check it).
If not, find out why it is not populated.
Is the "parties" field published to client? (you can run Proposals.find().fetch() in a browser console and see the results).
If not, check your publication.
Been struggling with an autoform to pre-fill the data, especially in hidden fields.
I have tried many things including using autoValue and defaultValue, but autoValue is validated on the server side and I need to grab a value from the page on the client side (the Router current route name) so it fails when getting looked up in the .clean function, and defaultValue takes a value, and won't take a function.
How to pass a value to a form to pre-fill some fields, without showing the field?
So, I posted the question because I have struggled and found the answer and wanted to share.
In the end, you can pass a doc attribute to a form
in the form it looks like:
{{> quickform
collection"mycollection"
id="formid"
type="method"
...
doc=mydoc
}}
and then you need a template helper to create the doc:
Template.myform_template.helper({
mydoc: function() {
return {field1: value1, field2:value2 };
}
})
You don't have to fill all the fields, just the one you want to pre-fill, just like the way the 'update' form works.
In order NOT to show this value in the form, I had tried to use the omitFields attribute, but that does not work as the field in the doc gets removed. so the only way I found was to declare the type of field in the schema as 'hidden' with
mycollection.attachSchema(new SimpleSchema({
field1: {
type: String,
optional: false,
autoform: {
type: "hidden"
}
}
}))
and here you are.
Now, on calling schema.clean(doc) in the method, the value is not really 'validated' since there is nothing to validate against in the schema, so you should validate those values yourself in the method call.
when i need prefill fields for an atoform, i use the AutoFom.hooks and in the template.html file i don't add these fields.
TemplateFile.html
{{#autoForm schema="Schemas.Myschema" id="idForm" resetOnSuccess="true" type="method" meteormethod="server/insertCustomizedTemplate"}}
{{> afQuickField name='Field1'}}
{{> afQuickField name='Field2'}}
{{> afQuickField name='Field3'}}
<button href="" type="submit" class="btn btn-success">
Send
</button>
{{/autoForm}}
TemplateFile.js
AutoForm.hooks({
idForm: {
before: {
method: function(doc) {
doc.Dummyfield1 = 'Harcoded Value';
doc.Dummyfield2 = 'Harcoded Value';
return doc;
}
},
onSuccess: function(formType, result) {
},
onError: function(formType, error) {
}
}
});