Search code examples
ember.js

Ember.js did-update function not tirggering


Ember 5.x

I have a parent component, Cases, and two child components. The CaseList has many items and the user can select one. This works. And the onCaseSelect is called. I want to have the NavBar see this change. Digging through the ember site, this site and lots of other sites, it seems like that updating 'this.selectedCase' should cause the @caseId in the nav-bar did-update to fire.


cases.hbs

<div class="flex">
    <CaseList @on-case-select={{this.onCaseSelect}}>
        {{outlet}}
    </CaseList>
    <NavBar @caseId={{@selectedCase}}></NavBar>
</div>

cases.js

@tracked selectedCase = ''

@action
onCaseSelect(caseId) {
    console.log('cases::onCaseSelect(caseId) {', caseId) // this is logging in the console
    this.selectedCase = caseId
    this.router.transitionTo('cases.case',caseId)
}

nav-bar.hbs

<div class="bg-slate-400 ml-auto flex" {{did-update this.onCaseIdUpdate @caseId}}>

nav-bar.js

@tracked caseId
@action
onCaseIdUpdate() {
    console.log('nav-bar::onCaseIdUpdate() {',this.args.caseId) // this NEVER fires
    this.caseId = this.args.caseId
}

Solution

  • Since you aren't using the element, why not git rid of {{did-update}} entirely?

    Try this:

    {{ (this.onCaseIdUpdate) }}
    
    onCaseIdUpdate = () => {
      this.caseId = this.args.caseId
    }
    

    however in this particular example, this will cause extra renders (as would any "effect"-like behavior (so effects in general should be used very very sparringly)).

    You may want something to handle your same behavior in a single render pass:

    get caseId() {
      return this.args.caseId;
    }
    

    Or if you need temporary local state until the next @caseId update, you could use @localCopy from https://github.com/tracked-tools/tracked-toolbox#localcopy

    @localCopy('args.caseId') caseId;