-
-
Notifications
You must be signed in to change notification settings - Fork 835
bug: Watching Native HTML Attributes requires at least one @Prop() declaration #5854
Description
Prerequisites
- I have read the Contributing Guidelines.
- I agree to follow the Code of Conduct.
- I have searched for existing issues that already report this problem, without success.
Stencil Version
4.18.3
Current Behavior
I want to @Watch() the host id attribute, but it requires at least one @Prop() set.
Without a @Prop() set, the @Watch() will not trigger.
With any @Prop() set, @Watch("id") will trigger on attribute change.
Expected Behavior
Preferred:
Setting an attribute watcher like @Watch("id"), triggers when changing the attribute;
Without requiring any @Prop() set.
Second best:
Might also agree with requiring at least an equal property like @Prop("id") as it is an attribute expected to be set on the component. But this might require additional code to reflect the exact HTML attribute behavior. (This side-effect is warned for by stencil's console output)
But in this case @Watch("id") is expected to only trigger when @Prop("id") is exact set.
System Info
System: node 20.11.1
Platform: darwin (23.5.0)
CPU Model: Apple M3 Pro (12 cpus)
Compiler: _PROJECT_/node_modules/@stencil/core/compiler/stencil.js
Build: 1716921701
Stencil: 4.18.3 😄
TypeScript: 5.4.5
Rollup: 2.56.3
Parse5: 7.1.2
jQuery: 4.0.0-pre
Terser: 5.31.0
Browser: Google Chrome 126.0.6478.114
### Steps to Reproduce
- Create starter Stencil project
- Generate simple component
- Add attribute `@Watch("id")` with corresponding handler
- Add the component to the `index.html`
- Start stencil `npm start`
- Open page and inspect web component
- Change / add the id attribute on the web component
- id watcher did not trigger
- Add a random `@Prop() foo` to component file
- Change the web component `id` attribute again
- `id` watcher did trigger
Component code:
```jsx
import { Component, Host, Element, Watch, h, Prop } from '@stencil/core';
@Component({
tag: 'test-input',
styleUrl: 'test-input.css',
shadow: true,
})
export class TestInput {
@Element() hostElement: HTMLElement;
private inputElement: HTMLInputElement;
// Comment @Prop() to see @Watch("id") not working
@Prop() fakeProp: string;
@Watch("id")
handleIdWatch(newId: HTMLElement["id"], currentId: HTMLElement["id"]) {
console.log(`idWatcher: ${currentId} ---> ${newId}`);
if (newId !== currentId) {
// set new input id
this.inputElement.id = newId;
}
}
render() {
return (
<Host>
<slot></slot>
<input type="text" id={this.hostElement.id} ref={element => this.inputElement = element} />
</Host>
);
}
}
Code Reproduction URL
Additional Information
I cant share my work code repo so I need to recreate a this code with a private account.
For now an empty repo, will fill later today.
EDITS
- [2024-06-25]: Added code reproduction URL