-
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
Allow overriding the default fields/widgets #371
Conversation
… descriptions & titles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the simplicity of your approach. I'd like to hear from @frassinier and @jmfrancois about it; do you guys feel like this could address your own use cases?
SchemaField: _SchemaField, | ||
TitleField: _TitleField, | ||
DescriptionField: _DescriptionField, | ||
}, this.props.fields); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were kept for backward compatibility purpose, but I'm glad seeing them going away. The change should be documented though (in the next release changelog).
StringField: require("./components/fields/StringField").default, | ||
NumberField: require("./components/fields/NumberField").default, | ||
TitleField: require("./components/fields/TitleField").default, | ||
DescriptionField: require("./components/fields/DescriptionField").default, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For legibility, we could create some load
helper, eg.
const load = comp => require(`./components/${comp}`).default;
const fields = {
ArrayField: load("fields/ArrayField"),
// ...
};
@olzraiti Could you provide sample of customization please? |
@frassinier for example if you would like to add a material theme, you would just override the specific widgets like so: Example 1: ThemesIf you need different themes, you could easily wrap your form like so: function ThemedForm(props) {
const themes = {
material: {
widgets: {
CheckboxWidget: CustomMaterialCheckbox
}
},
someOtherTheme: {
...what ever you would like to override
}
}
<Form
{...themes[props.theme]}
/>
} Now you have a form component which you can render with different themes: <ThemedForm theme="material" /> Example 2: non orderable arrays as defaultimport ArrayField from 'react-jsonschema-form/lib/components/fields/ArrayField';
function NonOrderableArrayField(props) {
return (
<ArrayField
{...props}
uiSchema={
...props.uiSchema,
"ui:options": {...props.uiSchema["ui:options"], orderable: false}
/>
);
}
<Form fields={{
ArrayField: NonOrderableArrayField
}} /> |
Love it, I will close my PR and help you by providing |
I'm glad we came to an agreement so fast, thanks for being so flexible. :) It's up to @n1k0 if this library should provide themes. I can think of two ways this library could go:
|
I didn't add many new tests or extend the documentation, since we are mostly removing a special case instead of adding new features (SOME of the fields/widgets have been overridable before this pull request, but not all. Now all of them are overridable). Maybe the documentation for a custom |
Good job @olzraiti ! I will work on a first theme impl ASAP :) |
@@ -358,6 +358,7 @@ class App extends Component { | |||
formData={formData} | |||
onChange={this.onFormDataChange} | |||
fields={{geo: GeoPosition}} | |||
widgets={{AltDateTimeWidget: () => <div id="#custom" >moi</div>}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really useful? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha wow... sorry for that :) It's "hi" in finnish.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks super good. A few nits and we're good to go, thank you 👍
@@ -897,6 +898,32 @@ If you're curious how this could ever be useful, have a look at the [Kinto formb | |||
|
|||
Props passed to a custom SchemaField are the same as [the ones passed to a custom field](#field-props). | |||
|
|||
### Customizing any fields or widgets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about Customizing default fields and widgets?
uiSchema={uiSchema} | ||
formData={formData} | ||
widgets={widgets} /> | ||
), document.getElementById("app")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may look super obvious to seasonned react developers, but maybe we should augment this section with an example of a reusable customized form class, eg.
const fields = {StringField: CustomString};
const widgets = {CheckboxWidget: CustomCheckbox};
function MyForm(props) {
return <Form fields={customFields} widgets={customWidgets} {...props} />;
}
render((
<MyForm schema={schema}
uiSchema={uiSchema}
formData={formData} />
), document.getElementById("app"));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo but +1
const customFields = {StringField: CustomString};
const customWidgets = {CheckboxWidget: CustomCheckbox};
function MyForm(props) {
return <Form fields={customFields} widgets={customWidgets} {...props} />;
}
@@ -31,7 +26,7 @@ function getFieldComponent(schema, uiSchema, fields) { | |||
if (typeof field === "string" && field in fields) { | |||
return fields[field]; | |||
} | |||
return COMPONENT_TYPES[schema.type] || UnsupportedField; | |||
return (COMPONENT_TYPES[schema.type] ? fields[COMPONENT_TYPES[schema.type]] : UnsupportedField) || UnsupportedField; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about:
const componentName = COMPONENT_TYPES[schema.type];
return componentName in fields ? fields[componentName] : UnsupportedField;
Closes #272, closes #310, closes #363. That's a neat example @frassinier, thanks for showing the potential this pull request brings! |
Thanks for this great collaborative effort! |
This release has been made possible by the combined work of @olzraiti, @maartenth, @vinhlh, @tiemevanveen , @dehli, @enjoylife, @pabloen, @israelshirk, @sjhewitt and @rom10. Thank you folks! Breaking changes ---------------- Support for passing `DescriptionField`, `TitleField` and `SchemaField` as `Form` props as been dropped in this release. You now have to always pass them through the `fields` prop. Deprecations ------------ * Leverage `ui:options` everywhere (fix #370) (#378) There's now a unique recommended way to specify options for widgets in uiSchema, which is the `ui:options` directive. Previous ways are still supported, but you'll get a warning in the console if you use them. New features ------------ * Allow overriding the default fields/widgets (#371) * Pass data to `FieldTemplate` as strings instead of as React components (#341) * Pass `schema` & `uiSchema` to the field template component (#379) * Add `ui:order` wildcard feature and improve error messages (#368) * Add support for widget autofocus (#288) * Array field optional sortability (#345) * Radio widget support for integers and numbers (#325) * Add support for inline radios and checkboxes. (fix #346) (#348) * Added ref to `FileWidget`. (#355) * Added `removable` and `addable` options for array items (#373) * Enable Windows development (#320) Enhancements and bugfixes ------------------------- * Fix `minimum/maximum==0` for `UpDownWidget` and `RangeWidget` (#344) * Handle numbers requiring trailing zeros with more grace (#334) * Pass empty title to `TitleField` instead of name (#311) * `asNumber`: return `undefined` when value is empty string (#369) * Use [glyphicons](http://getbootstrap.com/components/#glyphicons) for buttons by default. (fix #337) (#375) * Support old versions of React (#312)
Released in v0.41.0. |
Great job guys ! Thank you for all the effort ! |
I might have missed something but how do I change the default "number" input to an "updown" widget? For example, I want the following schema to produce an "updown" widget without providing the "ui:schema":
Also, why is the default widget for numbers a TextWidget and not something more numbers oriented? |
I guess because the TextWidget is the best compromise when you have no idea what kind of number one is talking about. For instance up and down button for a timestamp doesn't make any sense. |
@herzaso The documentation for custom widget is here: https://github.com/mozilla-services/react-jsonschema-form#custom-widget-components There apparently are some buildin widget for numbers: https://github.com/mozilla-services/react-jsonschema-form#for-number-and-integer-fields
|
@Natim , thanks for your comments. IMO, a better compromise would be to use a field that relates to a number and not to a string since I don't think there would be many real-world situations in which a user would want to have a text input for numbers (I'm not sure that showing a timestamp as is, and not as a date qualifies as a real-world situation). Either way, if the user has the ability to change the default widget, he could do so. Regarding my main question, I'm looking for a way to change the default widget since my form would be dynamic and I wouldn't want to loop over it. Since your answer refers to a specific field ( In that respect, the first link you provided (the uiSchema function) looks interesting but I do have 2 concerns:
|
I guess this pull-request allow you to do just that :) https://github.com/mozilla-services/react-jsonschema-form#customizing-the-default-fields-and-widgets |
Actually, I'm not sure it does as it rely on the default widget to replace and in my situation it will be TextWidget (and I don't want to replace the TextWidget). Update: I see that it relates to #637 although the actual behavior described there does not work for me ( |
Hey everyone, I am really struggling to find out how to override widgets globally. We have multiple json schema templates and customizing them individually is going to be painful. Just like MaterialUI we would like to use AntD components but I am not sure how to globally override Text inputs, checkboxes, radio buttons, select's etc. any pointer here would be appreciated. I have pretty much same requirement as @herzaso. |
@annjawn you'd have to customize each component individually. Eventually if people are interested they could contribute an antd theme (like for material ui) which would take a lot of work to initially make, but would then be easy for others to use. To globally override things, check out FieldTemplate in the docs. |
Reasons for making this change
This pull request is conflicting with #363 and #366. There is some heated discussion about the technical details in the comments of those pull requests. I'm offering this pull request because I had the code changes lying around anyway (as I have mentioned in #310). My intention is not to step on anyones toes - I'm merely offering a solution or at least some insight to the issue.
The reason why I have sitted on this for so long time is because I was waiting for input on the issues I have raised (#354, #310).
This approach has the benefit that we aren't introducing any new techniques or new API designs to solve the issue. All fields and widgets are simply overridable through the
fields
andwidgets
props.I didn't add any tests or update the documentation since this pull request is conflicting.
Checklist