Skip to content

bug: Watching Native HTML Attributes requires at least one @Prop() declaration #5854

@rvantonisse

Description

@rvantonisse

Prerequisites

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

https://github.com/rvantonisse/reproduction-stencil-issues/tree/rvantonisse/bug/5854-watching-native-html-attributes-requires-prop

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

Metadata

Metadata

Assignees

Labels

Bug: ValidatedThis PR or Issue is verified to be a bug within Stencil

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions