Stencil version:
@stencil/[email protected]
I'm submitting a:
Related code:
app-root.tsx
<app-product name='Corn flakes' quantity-left='4'></app-product>
app-product.tsx
@Watch('quantityLeft')
watchQuantityLeft(quantityLeft) {
this.button.disabled = (quantityLeft == 0);
}
Full source code here.
Current behavior:
watchQuantityLeft() is not called after component is loaded, which means what you see on the page does not reflect the component's current internal state and the button isn't disabled.
Expected behavior:
watchQuantityLeft() should be called.
Workaround:
Manually call the watchers after component is loaded :
componentDidLoad() {
// ...
this.watchQuantityLeft(this.quantityLeft);
}
Which can potentially be tedious if you have a bunch of them.
Same issue on: "@stencil/core": "~0.16.2"
Hi flawyte, on componentDidLoad you get the the dom node. But changing the disabled flag is not done on the dom-node itself, but only on the local reference. You wont need componentDidLoad and the watcher to disable the button based on the quantityLeft prop. Just add that logic to you render method, that is called whenever @prop or @state changes. You can do this via classes or with the basic disabled property of the button, like you did.
Using css classes:
render() {
const buttonClasses: Array<String> = ['basic-class'];
if (this.quantityLeft == 0) {
buttonClasses.push('basic-class--disabled');
}
return (
<div class='Root'>
<div class='Name'>{this.name}</div>
<button class={buttonClasses.join(' ')}>Hello</button>
<div class='QuantityLeft'>{this.quantityLeft} left</div>
</div>
);
}
or using disabled flag
render() {
const disabled: string = this.quantityLeft == 0 ? 'disabled' : '';
return (
<div class='Root'>
<div class='Name'>{this.name}</div>
<button class='Button' {disabled}>Hello</button>
<div class='QuantityLeft'>{this.quantityLeft} left</div>
</div>
);
}
hope this helps
I don't think it's a problem of local reference, because if you put a log inside watchQuantityLeft(), you'll see that it won't print either, which means the @Watch() method is never called with the initial quantity-left value while it was actually set on the element e.g. if you type productElement.quantityLeft it'll return 4.
IMO, the generally expected behavior is that by default the listener will be triggered for the initial value too. But it could also do so via an optional parameter, similar to Vue's immediate option.
I also think that this behaviour is the expected one but it is documented that this doesn't work this way, so I don't know if this is intended or could be fixed. Adding an optional parameter would be enough,but I don't know other workaround apart from calling the method again on componentDidLoad.
This is the expected behaviour.
I think it would be nice to pass some options to watch decorator. Something like
@Watch('propName', { immediate: true })
This way is implemented in Vue.js and currently it is really in demand.
Most helpful comment
I don't think it's a problem of local reference, because if you put a log inside
watchQuantityLeft(), you'll see that it won't print either, which means the@Watch()method is never called with the initialquantity-leftvalue while it was actually set on the element e.g. if you typeproductElement.quantityLeftit'll return4.IMO, the generally expected behavior is that by default the listener will be triggered for the initial value too. But it could also do so via an optional parameter, similar to Vue's
immediateoption.