I can't find any documentation regarding whether uniforms can make use of SimpleSchemas autoValue() function.
I tried making a uniforms: "something" key in the SimpleSchema, which were no help. In the docs it says remember to import uniforms packages first. What packages?
Some explanations about how uniforms handles this would have been lovely :)
I don't understand you, really.
If you have an uniforms: "something" in your SimpleSchema, then it will try to render a <something /> tag. This works like this:
uniforms is a string or a function, then use it as a component.What do you mean, by _make use of SimpleSchema autoValue()_? Calculating autoValues is having place in the clean method, so after the submit - how it should affect form itself?
Ah..
That explains alot! Thanks :)
And yes, i digged more into the SimpleSchemas autoValue() now, and found out I had misunderstood. I'm using it when inserting into the database, so it doesn't have anything to do on the client side.
Thanks alot :)
There is one use case, that i needed recently:
If you want to populate the form with default-values or auto-values, when no doc/model is specified. I then used the 'clean'-function of simpleschema to create an initial doc for the form:
const model = MySchema.clean({});
// later
I see!
Nice to know, macrozone :)
I know this is an old topic, but I think there's some inconsistency/confusion with autovalue. Consider the official demo from https://uniforms.tools/ and changing the schema to include autovalues:
new SimpleSchema({
date: {
type: Date,
defaultValue: new Date()
},
size: {
type: String,
defaultValue: 'm',
allowedValues: ['xs', 's', 'm', 'l', 'xl']
},
rating: {
type: Number,
allowedValues: [1, 2, 3, 4, 5],
uniforms: {
checkboxes: true
}
},
friends: {
type: [Object],
minCount: 1
},
'friends.$.name': {
type: String,
min: 3,
autoValue() { return 'foo' }
},
'friends.$.age': {
type: Number,
min: 0,
max: 150,
autoValue() { return 123 }
}
})
and then clicking on submit, results in "no error message for name/age" fields (whereas, without the autovalue, they are red and required) but the final model still does not have the values:
{
"date": "2017-02-13T08:12:22.373Z",
"size": "m",
"friends": [
{}
]
}
whereas, I would have expected, either this model with an error message, or a model including foo and 123 since there's no visual error on the form, nor one in the form's context.
So this is a big inconsistency, which may even be referred to as a bug.
For better context, please take a look at the screenshot:

On this image, we should have been able to see:
a) either the auto values within the resulting model
b) or required error messages on the form
@serkandurusoy autoValues are user decision. By default, validate is calling clean which is using them to provide default values _(there's a getAutoValues option)_. Demo is a _quick and dirty_ rather than a complete solution. To achieve _a)_, use clean manually, to achieve _b)_, use validator={{clean: false}} _(or similar)_ on your form (source).
I already saw that and that's one of the reasons I think this is a bug.
clean: true means, validation runs autovalues and therefore fields are set. Therefore, I expect to see them set on the model, too.
Furthermore, uniforms behavior is inconsistent with the actual state of form and its underlying validation data.
It should either return an error for the autovalue field or set the value to the model. However, uniforms does not set the error, but does not set the field either.
So, if you want us to use the clean method manually, you should either not run autovalues at all (and get the error) or get the value.
Default clean: true is a design decision, because most of us do clean the object before doing anything with it. You don't see the change in the model, because these fields are added by the clean just before the validation happens and this change is not mutating the model itself _(it was a reported bug)_.
I support the decision to have clean: true by default, because that's probably what most people want. And that's also what I want.
So about the bug regarding, model not being set. Where is this tracked? Are you planning a fix for it?
We've misunderstood. The bug was, that clean was mutating the state. It is wrong because form can't react to this change. That's why validate is only a check, not a mutator of the state.
Ok, I see that you've made this choice as a design decision. Thanks for the
information.
What is the recommendation for dealing with autoValues on the client-side validation? It sounds like there are three options:
(1) make fields with autoValue optional;
(2) put dummy hidden fields in the client with values that will be replaced by the result of autoValue() on the server;
(3) ignore the relevant errors with a custom onValidate handler.
Is there a more appropriate option? I'm thinking of created/updated timestamps, relationship ids, etc.
@micahalcorn: with current validators, both SimpleSchema bridges resolve autoValues before the validation. However, it doesn't change the model, so in onSubmit you have a _raw_ model. If you need them, then call .clean() by yourself. If it's not an answer, I probably didn't caught your problem.
@radekmie my validations are failing on all required autoValue & defaultValue fields. Everything works fine if I make those fields options.
import React from 'react';
import { AutoForm } from 'uniforms-bootstrap4'; // version 1.21.0
import { createContainer } from 'meteor/react-meteor-data';
import { Docs } from '../../../api/docs/docs';
import { log } from '../../../modules/logger';
class MyForm extends AutoForm {
onChange (k, v) {
// modify another field
super.onChange(k, v);
}
}
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleValidate = this.handleValidate.bind(this);
this.state = { pristine: true };
}
handleChange(k, v) {
this.setState({ pristine: !form.state.changed });
}
handleSubmit(model) {
// call method
}
handleValidate(model, error, callback) {
error && error.details.forEach((err, i) => {
Meteor.setTimeout(() => {
log(err.message);
}, i * 200);
});
callback(error);
}
render() {
const { props, state } = this;
const { doc } = props;
const { pristine } = state;
return (
<MyForm ref={f => form = f} schema={Docs.schema} model={doc} validate="onSubmit" onChange={this.handleChange} onSubmit={this.handleSubmit} onValidate={this.handleValidate}>
...
Could you post an example schema and reproduce it on uniforms.tools?
@radekmie yes, thanks. It looks like the issue arises with the use of collection2 autoValue properties.
...
createdAt: {
type: Date,
autoValue: function() {
if (this.isInsert) {
return new Date();
} else if (this.isUpsert) {
return {
$setOnInsert: new Date()
};
} else {
this.unset();
}
},
},
...
@micahalcorn: in this case, you can use extendedCustomContext (passed through validator prop) and assume that your form is for example an _insert form_. Otherwise, such schema won't work - we cannot assume or guess your schema context.
There is one use case, that i needed recently:
If you want to populate the form with default-values or auto-values, when no doc/model is specified. I then used the 'clean'-function of simpleschema to create an initial doc for the form:
const model = MySchema.clean({});
// later
Been a while, but I came across this thread going through a variation of the issue. Just wanted to add in case of future reference: Noticably I get the error that the bridge doesnt have 'clean' method. Make sure to use the actual schema for 'clean', not the bridge (confirm?).
Yes, you should use your SimpleSchema instance clean method - bridge does not expose such a method.
Most helpful comment
There is one use case, that i needed recently:
If you want to populate the form with default-values or auto-values, when no doc/model is specified. I then used the 'clean'-function of simpleschema to create an initial doc for the form:
const model = MySchema.clean({});
// later