-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #471: Drop default value initialization at the widget level. #476
Conversation
Grmbl the resulting Edit: these |
Blocked by tdegrunt/jsonschema#206 |
Unblocked with b9e2e6d |
1223673
to
8c5474f
Compare
I think we have a patch here. I've deployed its latest version to gh-pages, I'd appreciate feedback. |
@crumblix may I insist on having your feedback with this one? Thanks ;) |
Yes Grmbl indeed! I've tried it out and thought long and hard about it. Although initially for it, I think I'm now coming down against the array part of the changes. The main problem is that you cannot save the form for a NULL (or empty string) in the case of "A list of strings" Effectively these fields act as being "mandatory even though we haven't said they are. There isn't a * next to them so the user knows they are mandatory, and quite frankly I think we should be supporting a "no value" result in these cases. If we leave out the array changes the value comes through as "null". Which is probably closer than the alternative perhaps? It means we can test for a missing value in the formData and still allow submission. I'm not sure if in the array case we can do better than that can we? We can't remove the item or the order will be wrong, and I don't think we should error if the user hasn't entered anything. What do you think? I'd really be interested in some more feedback for other people too. I still like removing defaultFieldValue though in the base classes. |
Well, that's on purpose. A "list of strings" cannot contain a {
type: ["string", "null"]
} ... which is unfortunately not supported by the library at this moment, though I expect most users wanting actual strings instead of mixed arrays of null and strings anyway (well, I do).
Me too. Edit: Just for the sake of clarity, in the playground clearing a string field in an array will set |
I can't actually disagree with you, but I still have UI concerns. The problem is if I clear a string or clear a number (in the case of "Fixed array without buttons") I cannot submit the form. In the case of simple lists like "A list of Strings" I could agree that erroring might be the correct course of action and even make sense to the user, but in the other cases on that page where it's representing a complex object rather than a simple list it doesn't seem to work from a UI point of view. How about this. If we keep the change can we mark in the captions that the fields are mandatory on the "arrays as objects" cases? e.g. "A string value *" and "a boolean value *" and "additional item *" in "A List of fixed Items". (Note: We'd also need to remove the blank option on the boolean drop down, really make it mandatory). At least that way it will make sense to people using the forms. So if you are using arrays to represent objects the individual elements are mandatory. And if you don't want mandatory items in the array you should type your objects explicitly? Make that clear in the documentation? |
Wait, what should be the right behavior for the "No add, remove and order buttons" section then? Should we just remove the string field entirely when clearing it? That would really surprising UX to me. A fixed list of strings requires every items to be an actual string, so the form behavior makes perfect sense to me.
That makes perfect sense, I'll try to add this to the patch.
That would certainly be a possibility, but it would feel to me like rewriting the jsonschema spec again. Why would one use jsonschema at all if to not know about its strict data structure validation capabilities? I understand that for some people *that's just a way to build forms", but with forms come data models, and with data models come types and validation, so that's fair game imho. We'll certainly need to make that statement as clear as possible early in the docs, sure. |
Oh I agree we can't remove the field entirely in the array case, that would surprise me as well. No, in the case of simple lists like "No add remove buttons" the error is currently fine (although perhaps unnecessary if the widget is marked as mandatory since hopefully the mandatory constraint will kick in first and make more sense to the user). I think the right behaviour from a UI point of view is if it acts like a mandatory field treat it as one. If I can't submit the form with an empty control effectively we only support mandatory for arrays. If we implemented your other suggestion above: {
type: ["string", "null"]
} ... then that could change. But in the meantime it's mandatory, and developers need to understand if they use arrays to represent objects that's what they'll get. |
OK. So I've tried reverting the array changes above and putting "required={true}" against the two SchemaField declarations in ArrayField.js. That looks to me like it fixes the problem from all angles. You even can have the nice HTML5 "required" warnings instead of the validation ones if you want. When (or if) we support null in the schema like you suggest above then we remove those two lines setting "required" and we're good. Thoughts? |
About
, I think it only meaningful when it is a property of an object. So, I would prefer to have this in the object field onPropertyChange = (name) => {
return (value, options) => {
if(isEmpty(value)){
const {[name]:_, ...newFormData} = formData;
}else{
const newFormData = {...formData, [name]:value};
}
this.props.onChange(newFormData, options);
};
}; where "isEmpty" could be customizable via registry. (I would be happy if isEmpty includes {} and []). This also guarantee the from will alway return a non-null value such as |
I feel that handling the default value is the source of evil. It make both users and the form want to take control over the fromData. class Foo extends Component {
constructor(props){
super(props);
this.state = {value:undefined}
}
clear = ()=>{
this.setState({value:undefined});
}
onChange = ({target:{value}})=>{
this.setState({
value:value===""?undefined:value
});
}
render() {
return <div><input
type="text"
defaultValue="foo"
value={this.state.value}
onChange={this.onChange}/>
<button onClick={this.clear}>clear</button>
</div>
}
} where the "defaultValue" is the exactly same as the default value in the schema.
So I believe it is necessary to differentiate "controlled" and "uncontrolled" formData. |
@crumblix I'd like you to review 53e4b51 Non-nullable array item widgets are now marked as required. I didn't remove the array mapping to mark blanked string fields as Edit: Deployed to gh-pages for easier QA. |
Yes! Moving the logic to isItemRequired is good. :) However, I could be wrong, but I don't think we need new line at 422 in ArrayField.js. It's not currently even being unpacked in renderArrayFieldItem, and renderArrayFieldItem calls isItemRequired anyway. Overall I think it's an elegant solution for now. |
Yeah that was a leftover 😊 On next green build I'm gonna land this and make a release. |
Excellent :) |
Highlights --- - Improved performance and reactivity. - More consistent validation behavior and UX for array field items. Backward incompatible changes --- - `ObjectField` and `ArrayField` are now stateless components, their local state handling has been dropped entirely, resulting in large performance improvements. - The `defaultFieldValue` helper from the `utils` module has been removed, as it wasn't used anymore. New features --- * Fix #411: Enable required field on radio options. (#469) * Spread `formContext` to `ArrayTemplateField`, `files` and `multiselect` arrays (#456) * From #471: Non-nullable array item fields are now marked as required in the UI. Bugfixes --- * Don't pass consumed `SchemaField` class names to child component (#439) * Turn `ObjectField` and `ArrayField` into stateless components (#480) * Fix #471: Drop default value initialization at the widget level. (#476) Kudos --- Special thanks to @crumblix and @knilink for their help on this release. You guys rock!
Released in v0.43.0. |
Hi, What's the situation for non-array string fields? I think that resetting to the default value when clearing the field is a good practice. I think that the example that led to this (where "bazinga" was auto filled) was a specific case. Most of the time we want string fields to have empty strings as default value, I think this is a bad decision and I'm having a hard time implementing the empty string value with this form |
Ok so please send a PR. Thank you. |
Implements simple solution suggested by @crumblix in #471 (comment)
Deployed to gh-pages for easier testing.
r=? @crumblix