-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
feat: dependent fields #3891
base: main
Are you sure you want to change the base?
feat: dependent fields #3891
Conversation
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.
Thanks again @barthc for pushing another highly requested feature.
Sorry for taking so long to reply.
Looks like the field will be hidden when the condition is met and not shown only when the condition is met. Am I correct?
Doing the following seems more intuitive to me (and matches #565 (comment)):
- {label: "Continent", name: "continent", widget: "select", default: '', options: ['Europe', 'Asia']}
- {label: "Europe", name: "countries_europe", widget: "select", options: ['spain', 'italy', 'france'], conditions: [{ fieldPath: 'continent', oneOf: ['Europe'] }] }
- {label: "Asia", name: "countries_asia", widget: "select", options: ['india', 'japan', 'china'], conditions: [{ fieldPath: 'continent', oneOf: ['Asia'] }] }
WDYT?
Using the wildcard
*
is great for supporting lists. I wonder if we should create a dedicated data structure to hold the tree of widgets since we already passparentIds
for the nested validation.
The field will be hidden when any(not all) of the conditions are met, I think we should change
The empty string is just to hide both
Not sure how the tree structure will be useful here if you can explain with some codes, better. The |
With hide notation each time someone adds a select option it will require editing all other fields or the condition will break right? With show notation you'd only need to do: - {label: "Continent", name: "continent", widget: "select", default: '', options: ['Europe', 'Asia']}
- {label: "Europe", name: "countries_europe", widget: "select", options: ['spain', 'italy', 'france'], conditions: [{ fieldPath: 'continent', equals: 'Europe' }] }
- {label: "Asia", name: "countries_asia", widget: "select", options: ['india', 'japan', 'china'], conditions: [{ fieldPath: 'continent', equals: 'Asia' }] } Then adding a new option: - {label: "Continent", name: "continent", widget: "select", default: '', options: ['Europe', 'Asia','America']}
- {label: "Europe", name: "countries_europe", widget: "select", options: ['spain', 'italy', 'france'], conditions: [{ fieldPath: 'continent', equal: 'Europe' }] }
- {label: "Asia", name: "countries_asia", widget: "select", options: ['india', 'japan', 'china'], conditions: [{ fieldPath: 'continent', equal: 'Asia' }] }
- {label: "America", name: "countries_america", widget: "select", options: ['mexico', 'us'], conditions: [{ fieldPath: 'continent', equal: 'America' }] }
Let me dig into that a bit more. |
Agreed. |
b02bc89
to
4874bfe
Compare
When will this feature will be available? |
See my comment here #565 (comment) |
Closing this as stale. We can revisit in the future, or if someone wants to pick it up per #3891 (review) |
Hey there! I'm in need of this so happy to try to pick this up again from #3891 (review) |
sooo is this not a feature? seems like a really basic need for ANY CMS lol |
@larenelg I reopened this PR if you're still interested |
Could this use case be solved by making variable types work for object widgets? That's effectively what we do, by having lists with min and/or max set to 1. It would have the benefits of being (presumably) easier to implement/maintain and easier to understand by users. |
@mmkal can you explain how that would enable the conditional feature? Maybe with an example? Thanks |
Sure, I'll have to adjust the original example, because the example from the OP, and proposed solution, is already a list so can just use variable types right now: #565 (comment) - label: structure
name: structure
widget: list
types:
- name: copy
widget: object
fields:
- name: text
widget: markdown
- name: productCircle
widget: object
fields:
- name: text
widget: markdown
- name: src
widget: image
- name: infographic
widget: object
fields:
- name: text
widget: markdown
- name: src
widget: image
- name: overlay
widget: image
... I think this is much easier to follow when looking at the config too. Answering the question "what subfields does an infographic have" doesn't involve darting around and looking at all of the condition labels, and mentally parsing the custom condition syntax (which has to be learned and remembered). Worth noting, there is one slight downside which is that fields in common between the various types have to be defined explicitly on each. That can be solved fairly easily with yaml references (or my team generate the config from typescript anyway so we can use helper methods and strong types), but also more importantly, by the same token, it allows for the different types to independently define their fields. So, IMO the original issue could be closed with a suggestion like this. But if someone wanted to make a non-list field like this, that is a missing feature. It'd be nice to be able to do the same thing for objects, e.g.: - label: structure
name: structure
widget: object # 👈 not supported right now, only `widget: list` is
types:
- name: copy
widget: object
fields:
- name: text
widget: markdown
- name: productCircle
widget: object
fields:
- name: text
widget: markdown
- name: src
widget: image
- name: infographic
widget: object
fields:
- name: text
widget: markdown
- name: src
widget: image
- name: overlay
widget: image
... I think the use case for that is smaller, but it could make sense on folder collections - different entries could use different |
Thanks for the comment @mmkal. This is a feature that has been discussed many times with many proposed solutions, so I would like to take some time with the team to carefully review them and decide where we want to go. It is one of the most requested features, so it's important not to rush. |
any updates? come on |
Here's something we've started doing, along the lines of my above comment, but also adds support for import {List} from 'immutable'
import React from 'react'
import CMS from 'decap-cms-app'
export function optionalizeObject() {
const listWidget = CMS.getWidget('list')
const objectWidget = CMS.getWidget('object')
class NewObjectControl extends React.Component<any> {
render() {
if (this.props.field.get('required') === false || this.props.field.get('types')) {
return (
<listWidget.control
{...this.props}
onChange={(e: List<any>) => this.props.onChange(e.get(0))}
value={List([this.props.value].filter(Boolean))}
/>
)
}
return <objectWidget.control {...this.props} />
}
}
CMS.registerWidget('object', NewObjectControl, listWidget.preview)
} Here's a demo: collection definition: {
label: 'test test',
name: 'test',
folder: 'shared/content/src/data/marketing/test',
slug: '{{slug}}',
format: 'yml',
create: true,
fields: [
{
name: 'some_string_field',
widget: 'string',
},
{
name: 'structure',
widget: 'object',
types: [
{
name: 'copy',
widget: 'object',
fields: [
{name: 'text', widget: 'markdown'},
],
},
{
name: 'productCircle',
widget: 'object',
fields: [
{name: 'text', widget: 'markdown'},
{name: 'src', widget: 'image'},
],
},
{
name: 'infographic',
widget: 'object',
fields: [
{name: 'text', widget: 'markdown'},
{name: 'src', widget: 'image'},
{name: 'overlay', widget: 'image'},
],
},
],
}
]
}, How it renders in the UI: Screen.Recording.2024-01-11.at.11.25.01.AM.movFiles generated by the above: Bonus: this also improves support for In the spirit of not adding complexity to both the product and the codebase, I think the above would be a better solution than this pull request, so I would propose the following changes instead:
1 can be done first, then 2. I'd be happy to open a PR. @martinjagodic what do you think? |
@mmkal I like this a lot! It achieves a lot with very little intervention. A PR for solution 1 would be amazing. |
Closes #565
Based on comment #565 (comment), came up with the following:
conditions
which should hold an array of objects.fieldPath
attribute to reference the field, wildcards*
are supported as well similar to relation widget attrs. And any one ofequal
,notEqual
,oneOf
andpattern
config option.So based on the issue's OP, a config like so would work.
Example config that tries to mimic dynamic dropdown:
To do: