Coming from a React background, I'm having issues understanding EmberJs "Tracked" concept. On paper it shouldn't be different from "React state".
So what I have understood is that when we anotate a property with @tracked
it should cause a re render when there is a change in this property.
Please take a look at the code below:
ProductItemComponent
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class ProductItemIndexComponent extends Component {
@service('cart') cartService;
@tracked addedToCart = false;
@action
checkItemInCart(id) {
if (this.cartService.items.findBy('id', id)) {
this.addedToCart = true;
} else {
this.addedToCart = false;
}
}
}
Template,
<div class="card-container">
<div class="card product-item" {{did-insert (fn this.checkItemInCart @item.id)}}>
<img src={{@item.image}} class="product-image card-img-top" alt="...">
<div class="card-body">
<h5>{{@item.title}}</h5>
</div>
<div class="footer">
<p class="card-text"><span class="badge badge-secondary"><strong>Price: </strong>{{@item.price}}</span></p>
<button type="button" class="btn btn-warning" {{on 'click' (fn @handleCartAction item)}}
disabled={{this.addedToCart}}>Add
to cart</button>
</div>
</div>
</div>
When I first render the component I'm checking if the current item is present in the cart using {{did-insert (fn this.checkItemInCart @item.id)}}
and if its present I'm switch the tracked property @tracked addedToCart = false;
to true else false.
In theory, this should disable my button in my productItem template as soon as it finds the Item in the cartService
. It only works when I go to another page and then come back.
But there is no rerender of the page. Can someone help me understand what I might be doing wrong?
Thank you in advance
Your problem is that
checkItemInCart
is called only once, soaddedToCart
is not updated oncecartService.items
were changed.I think proper solution would be to make
addedToCart
depends oncartService.items
anditem
For this to work
cartService.items
should also be tracked property, and be updated with methods likepushObject
, see Why won't my tracked array update in Ember Octane?