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) {
}
}
});
Related
I was using v-model to handle inputs in a form, I had to change it to bind props values, at first input was like
<input type="text" class="form-control" placeholder="" v-model="username">
and now it looks like
<input type="text" class="form-control" placeholder="" v-bind:value="modelData.username" v-on:input="username = $event.target.value">
modelData is coming in props. and it has username.
when Using model, in data, i had defined
data: () => {
return {
username: ""
}
},
and It was working fine, but after changing it to v-bind and v-on,
My question is how I can now get the value of username in methods? as in past, I was getting it as this.username to get the value and also clear it as well but now how I can get username in
methods: {}
I have a button to save input
<button class="btn btn-secondary" type="button" #click="validateFormAndSave($event)">Save</button>
When validateFormAndSave get called I can have this.username right now I cannot get the value? But the Vue Doc says v-model and v-bind:value& v-on:input are the same?
UPDATE:
There can be and cannot be some value already there in username, as it being filled with props value, So v-on:input="username = $event.target.value" don't get the already written value but the only new one you entered? or edit it? Why is it so? is there any method for just to get what anyone typed in there or already been typed?
UPDATE:
This is getting very ambiguous. So for now.
1. I can set v-bind:value, But I cannot get it in methods without editing it.
2. I cannot set this.username = "" and it will not be removed from input as well.
3. #input only get what you newly typed not what already in there
v-model is just syntax sugar for =>
<input :value="modelValue" #input="modelValue = $event.target.value"/>
If you want something else, it's very easy to do. Just change the update side to onInput:
<input
class="form-control"
:value="username"
#input="username = $event.target.value"
>
Then
data: () => {
return {
username: ""
}
},
mounted()
{
this.username = this.modelData.username;
},
methods:{
consoleUsername() {
console.log(this.username);
}
}
The best possible solution can be when you are getting your data from props and also loading it a form for v-models.
Using watch feature of Vue component.
First I added props as
export default {
props: ["vendorModelData"],
and then I pass it through the watch to v-model
watch: {
vendorModelData() {
this.updatePropsValue(this.vendorModelData)
console.log("data updated")
}
},
in this way, it always loads differently when Props get changed. This way I got be using v-model as well as load data from props to it.
I found it useful for me.
I'm using v-validate with Vue. I'm trying to figure out how to force v-validate to update rules. For example, I have something like this:
<template>
<div v-for="field in fields">
<input :name="field.name" v-validate="field.rules">
</div>
</template>
<script>
export default {
data() {
fields: [
{
name: "city",
rules: {
included: []
}
}
]
}
}
</script>
As you can see, my "included" array is empty on page load. I get the array from an AJAX request, and then I update my data:
this.fields[0].rules.included = cities
But v-validate doesn't seem to acknowledge the newly-added array. It only works if I hardcode the cities into my data. How can I force v-validate to respond to the updated rules?
Vue.js is unable to track updates on nested reference types.
Try:
let fields = [...this.fields]
fields[0].rules = cities
this.fields = fields
Use Vue.set to track changes : https://v2.vuejs.org/v2/guide/reactivity.html
Vue.set(this.fields[0], 'rules', cities);
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'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
I have a route that displays a list of posts and also a form for creating a new post.
posts_route.js.coffee:
Fortchan12.PostsRoute = Ember.Route.extend
model: ->
Ember.RSVP.hash
posts: #get('store').findAll 'post'
newPost: #get('store').createRecord 'post'
actions:
create: (post) ->
post.setProperties
name: this.controller.get('name')
body: this.controller.get('body')
photo: this.controller.get('photo')
post.save()
and here is the handlebars template:
<h2>make a new post</h2>
<form {{action 'create' newPost on="submit"}}>
{{#if isSaving}}
<p>saving post...</p>
{{/if}}
<p>{{input type="text" value=name}}</p>
<p>{{textarea value=body}}</p>
<button type="submit">Create</button>
</form>
<h2>posts</h2>
{{#each posts}}
{{name}} says
{{body}}
{{created_at}} {{#link-to 'post' this}}
{{id}} {{/link-to}}
<br />
This seems to work fine, but I want to clear out the form after it is submitted and saved so I can make another post. I can do this in the create action in the route to clear out the form (although it doesn't seem to clear out the file input field):
self.controller.setProperties({name: '', body: '', photo: ''})
but that doesn't seem to 'reset' the model, when I submit the form again its trying to PUT to /posts/:id, instead of POST to /posts:
PUT http://0.0.0.0:3000/posts/70 404 (Not Found)
I'm not exactly sure what I am supposed to do, I've read that using setupController is an option but I'm not sure how to do that with using multiple models in my route like I am.
You'll want to create a new record as well, the page still has a reference to the other record, which you saved, and now that record has an id, which is why its trying to update that record (excuse the javascript).
actions:
create: (post) ->
self = #
post.save().then(function(){
self.set('controller.newPost', self.get('store').createRecord('post'));
});
Psuedo code mix for using all
model: function(){
return Ember.RSVP.hash({
posts: #get('store').findAll 'post',
newPost: #get('store').createRecord 'post'
});
},
setupController: function(controller, model){
controller.set('posts', this.get('store').all('post'));
controller.set('newPost', model.newPost);
}
reversed computed property
on the controller
reverseProperty: function(){
this.get('posts').sortBy('foo').toArray().reverse();
}.property('posts.[]')
Have you tried resetting the model like this?
#controller.set('content', #get('store').createRecord('post'))