Skip to content

Potentially ambiguous_inputNode() getter #2616

@gerjanvangeest

Description

@gerjanvangeest

Hi!
At some point we got a report that our textarea version based on the lion implementation of the very same field, has the following problem:

When the browser extension called "LanguageTool" is active, the character-counter does not work

~ clarification: the counter is a part added in OUR version

Nonetheless, in the process of investigating the problem, we finally discovered what was the root of it, namely:

  1. Extension "Language Tool" creates in the DOM, before all targeted inputs, the tags lt-mirror (this shall then create an overlay with the highlights and etc.)
  2. Important is, that this lt-mirror tag is slotted to slot="input" likewise the textarea element
  3. This causes value getter to work improperly, since it takes the value from the this._inputNode

source: form-core/src/FormatMixin.js

get value() {
    return this._inputNode?.value || this.__value || '';
}
  1. The this._inputNode is defined in the FormControlMixin where from the definition, it shall be the first child, which is assigned to a certain slot (.find method is happy with the first result):

source: form-core/src/FormControlMixin.js

get _inputNode() {
    return /** @type {HTMLElementWithValue} */ (this.__getDirectSlotChild('input'));
}
__getDirectSlotChild(slotName) {
    return /** @type {HTMLElement[]} */ (Array.from(this.children)).find(
        el => el.slot === slotName,
    );
}
  1. In the presence of lt-mirror (which are always rendered before), the this._inputNode shall adapt value of lt-mirror instead of the textarea element

Thereby, we propose to change the get _inputNode() implementation to be more specific, in case similar scenarios happen in the future.

In our component, we've overridden the getter to:

get _inputNode() {
    return this.querySelector<HTMLTextAreaElement>('textarea[slot="input"]')
}

but of course our component is "specific" (eg. we know it shall be textarea). The FormControlMixin will have to be more general, but still, simultaneously more specific than the current one I guess.

PS: For the scenario to get place, you have to activate the extension, and what's more important, start typing. Only then the problem appears. On the initial load, the getters work properly:

PS II: You may see, that invoking .value prop on lt-mirror tag works properly, returning the same value as the textarea. That is however, the cause of ambiguous behavior of the component in fact. The LanguageTool extension uses at some point a querySelector to connect lt-mirror tags with the inputs, but since it uses document.querySelectorAll(...), it cannot penetrate the shadowRoot, unless the content is slotted. In such situation the problem with the counter appears

Hopefully the description of the problem is clear

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is needed

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions