Conversation
…ut and parent gets a mutation observer to update children
…ementProp-and-get-mutation-observer-on-parent
|
I implemented this new pattern to just the Or I can put all other properties that need to be inherited in this PR as well since most of the work is done. I would just need to know which additional ones need to be inherited ( Added "[Erik/Eliza]: Pattern Discussion: Parent <> Child Property Relationships" for the next meeting. |
getElementProp on child is factored out and parent gets a mutation observer to update children
getElementProp on child is factored out and parent gets a mutation observer to update childrengetElementProp on child is factored out and parent gets a mutation observer to update children
|
|
||
| private passPropsToAccordionItems = (): void => { | ||
| ( | ||
| Array.from( |
There was a problem hiding this comment.
Can we use the existing this.items instead of querying for the child items again? I suppose this.items may not always be populated at connectedCallback but should be in componentDidLoad
componentDidLoad(): void {
...
this.passPropsToAccordionItems();
}
and
private passPropsToAccordionItems = (): void => {
this.items.forEach((el) => (el.scale = this.scale));
};
Seems to work reliably.
There was a problem hiding this comment.
This makes sense as long as this.items gets updated when accordion-items get added or removed from the light dom. Is this currently handled in any way?
There was a problem hiding this comment.
Yeah good point the internal registration events are kind of an outdated pattern and wouldn't respond - slot change observer that responds to addition / removal of children and updates this.items is probably better. There's a handful of our ... more senior 👴👵 ... components that could probably benefit from a change like that.
| await page.waitForChanges(); | ||
|
|
||
| expect(await accordion.getProperty("scale")).toEqual(scale.l); | ||
| expect(await item1.getProperty("scale")).toEqual(scale.m); |
There was a problem hiding this comment.
Don't we want the scale of calcite-accordion and calcite-accordion-item to match in this case - shouldn't let folks set scale "m" on the child if the parent is "l". (assuming scale on calcite-accordion-item is internal property)
There was a problem hiding this comment.
Seems logical that if calcite-accordion-item is an internal property we shouldn't be letting users set it to a different scale, but based on other comments looks like this is also part of tomorrow's Child Property Relationships discussion.
There was a problem hiding this comment.
Don't we want the scale of
calcite-accordionandcalcite-accordion-itemto match in this case - shouldn't let folks set scale "m" on the child if the parent is "l". (assuming scale oncalcite-accordion-itemis internal property)
I agree it seems odd to allow this, but if you think about it, this pattern breaks component autonomy. When a component defines its own scale prop, I as a developer expect it to honor whatever value I'm explicitly setting it to, excepting the default fallback value. If a parent value comes in and overrides that value I've explicitly set on the child, the property pattern on that child component no longer behaves according to standard convention.
There was a problem hiding this comment.
Yeah, although if the property is internal and is set by / managed by the parent maybe I wouldn't expect to be able to set this at all, as its undocumented. Though to follow through on that the scale probably shouldn't have the default to "m" until it receives the scale from calcite-accordion.
There was a problem hiding this comment.
This same principle applies to object inheritance in programming. If I have Object A that defines a foo property, an Object B that extends Object A, I don't expect setting the foo property on Object A to override what I've explicitly set it to on Object B. I expect the lowest level of specificity on that property to win above all others.
There was a problem hiding this comment.
Right - but its not a public property (or, is proposed to be an undocumented, internal property) - so the test case of it being set in that way should not be valid?
There was a problem hiding this comment.
Yeah, although if the property is internal and is set by / managed by the parent maybe I wouldn't expect to be able to set this at all, as its undocumented. Though to follow through on that the scale probably shouldn't have the default to "m" until it receives the scale from
calcite-accordion.
For sure. I think with a component like accordion, its children items are so tightly interwoven with the parent that this pattern does make sense where you would explicitly control children properties like scale from the parent level. It gets trickier when you have child components that can live standalone by themselves like radio-button and tile-select where they need to work on their own regardless if their corresponding parent wrapper component is being used.
Right - but its not a public property (or, is proposed to not be an undocumented, internal property) - so the test case of it being set in that way should not be valid?
Agreed. I think if we mark these properties as internal, and call out in our documentation that modifying internal properties is not supported, then this pattern can be adopted for certain parent/child component systems.
| expect(await item1.getProperty("scale")).toEqual(scale.s); | ||
|
|
||
| const icon1: E2EElement = await page.find(`calcite-accordion-item[id='1'] >>> .${CSS.iconStart}`); | ||
| expect(await icon1.getProperty("scale")).toEqual(scale.m); |
There was a problem hiding this comment.
Should we instead expect this icon be a scale s based on the scale s of the parent calcite-accordion-item?
There was a problem hiding this comment.
We should probably add this to tomorrow's Pattern Discussion: Parent <> Child Property Relationships. From what I understand while we expect a parent to update children where these 2 have a parent/child relationship (as in accordion and its item), element and its slotted icon don't have that relationship and are expected to have independent scales. But in this particular case, it does feel a bit odd. Erik also brought up that we should not override an item with the parent if a user sets it individually to a different scale, although I'm not sure what the use case for that would be.
There was a problem hiding this comment.
Erik also brought up that we should not override an item with the parent if a user sets it individually to a different scale, although I'm not sure what the use case for that would be.
Not sure what the specific use case would be either, but I still think that if the scale property is explicitly applied either as an attribute or by setting the property directly on the child component, that this value should be honored and not overridden by the parent component. We can actively discourage doing this in the documentation, and encourage users to set the value at the parent level to ensure visual consistency, but I don't think we should break from convention with regards to how property values are honored at the individual component level.
|
This PR has been automatically marked as stale because it has not had recent activity. Please close your PR if it is no longer relevant. Thank you for your contributions. |
|
Closing this, as it was resolved in #7191. |
Related Issue: #6038, #5698
Summary
getElementPropon child is factored out and parent gets a mutation observer to update children.