GAUD-10044: Create FormElementContainerMixin mixin#7016
Conversation
- Handles the use case for nested form container components that are not also a form controller - Adds unit test - Updates the demo page to demonstrate this new behavior
|
Thanks for the PR! 🎉 We've deployed an automatic preview for this PR - you can see your changes here:
Note The build needs to finish before your changes are deployed. |
There was a problem hiding this comment.
This change in combination with the changes at components/form/form-helper.js is how now the form is able to "find" these custom form element containers
…data section, reuses the input and input label styles
| @@ -1,9 +1,11 @@ | |||
| import './form-element.js'; | |||
| import '../../inputs/input-text.js'; | |||
There was a problem hiding this comment.
This is needed because the class defined using defineCE uses it within its render method.
| required | ||
| class="d2l-input"> | ||
| </div> | ||
| <d2l-input-text label="Middle Name" name="middle-name" minlength="4" maxlength="8"></d2l-input-text> |
There was a problem hiding this comment.
Should have an import for input-text.js and input-number.js, which can be removed from form-panel-demo.js.
| required | ||
| > | ||
| <d2l-input-text | ||
| id="nested-telephone-input" |
There was a problem hiding this comment.
Ok -- could also be elem.querySelector('d2l-input-text') or elem.querySelector('d2l-input-text[name="phone"]').
bearfriend
left a comment
There was a problem hiding this comment.
Mostly a bunch of nits
| <d2l-input-group> | ||
| <div> | ||
| <label for="native-input" class="d2l-input-label d2l-input-label-required">First Name</label> | ||
| <input id="native-input" |
There was a problem hiding this comment.
| <input id="native-input" | |
| <input | |
| id="native-input" |
| render() { | ||
| return html` | ||
| <label for="nested-native-input">Name</label> | ||
| <input id="nested-native-input" |
There was a problem hiding this comment.
| <input id="nested-native-input" | |
| <input | |
| id="nested-native-input" |
|
|
||
| export const isCustomFormElement = (node) => isCustomElement(node) && !!node.formAssociated; | ||
|
|
||
| export const isCustomFormElementContainer = (node) => isCustomElement(node) && !!node.isCustomFormElementContainer; |
There was a problem hiding this comment.
| export const isCustomFormElementContainer = (node) => isCustomElement(node) && !!node.isCustomFormElementContainer; | |
| export const isCustomFormElementContainer = node => isCustomElement(node) && Boolean(node.isCustomFormElementContainer); |
| const getElementChildren = (ele) => { | ||
| if (isCustomFormElementContainer(ele)) { | ||
| return ele.shadowRoot.children; | ||
| } | ||
|
|
||
| return ele.tagName === 'SLOT' && ['primary', 'secondary'].includes(ele.name) ? ele.assignedNodes() : ele.children; | ||
| }; |
There was a problem hiding this comment.
Typical convention is just el, or maybe elem for more public-facing API stuff I guess. Sort of a nit, but sort of not, for consistency.
| const getElementChildren = (ele) => { | |
| if (isCustomFormElementContainer(ele)) { | |
| return ele.shadowRoot.children; | |
| } | |
| return ele.tagName === 'SLOT' && ['primary', 'secondary'].includes(ele.name) ? ele.assignedNodes() : ele.children; | |
| }; | |
| const getElementChildren = el => { | |
| if (isCustomFormElementContainer(el)) { | |
| return el.shadowRoot.children; | |
| } | |
| return el.tagName === 'SLOT' && ['primary', 'secondary'].includes(el.name) ? el.assignedNodes() : el.children; | |
| }; |
There was a problem hiding this comment.
I will apply it thanks. but in terms of consistency the whole file uses the ele variable's name (reason why I stick with it). Having that said, I agree with you about the convention, but here seems the convention is not our convention or at least in this file.
There was a problem hiding this comment.
Oh sorry, I peeked at the history and thought you had just recently added all the ele uses
| const _findFormElementsHelper = (ele, eles, isFormElementPredicate, visitChildrenPredicate) => { | ||
| if (isNativeFormElement(ele) || isCustomFormElement(ele) || isFormElementPredicate(ele)) { | ||
| eles.push(ele); | ||
| } | ||
| if (visitChildrenPredicate(ele)) { | ||
| const children = ele.tagName === 'SLOT' && ['primary', 'secondary'].includes(ele.name) ? ele.assignedNodes() : ele.children; | ||
| const children = getElementChildren(ele); | ||
| for (const child of children) { | ||
| _findFormElementsHelper(child, eles, isFormElementPredicate, visitChildrenPredicate); |
There was a problem hiding this comment.
It won't let me make a suggestion here, but same thing with el. Maybe elems for the plural?
Jira
GAUD-10044
Description
Currently the
d2l-formcomponent is able to find nested forms, native form controllers and d2l custom form controllers (through theFormElementMixin)there is still 1 use case where we just want to group the form controllers logically in a custom web component -- let's call it form form element container. this is because the form is big enough so we want to encapsulate portions of it in logically and semantically groups of controller. In this case, the form has no chance to find those nested form controllers within the form element container.
Solution
To address this we decided to implement the
FormElementContainerMixinwhich accomplishes that.