Search code examples
ember.jscomputed-propertiescomputed-observableember-classic

How can I rerender when object (a dictionary) changes?


I have the following .hbs

<button {{action "addToObject"}}>
    Add to Object
</button>

<br />

{{#each this.sortedDictionary as |item|}}
    {{item.name}}<br />
{{/each}}

and the corresponding .js code for it:

import Component from '@ember/component';
import EmberObject, {set, computed, observer} from '@ember/object';

export default Component.extend(
{
    myDictionary: null,
    counter: 0,



    init()
    {
        this._super( ...arguments );

        console.log( "test-comp init" );

        this.myDictionary = {};

        set( this.myDictionary, "hello", "42" );
    },



    sortedDictionary: computed( 'myDictionary', function()
    {
        let sortedDictionary = [];

        if ( this.myDictionary ) 
        {
            const keys = Object.keys( this.myDictionary );

            keys.sort();

            console.log( "test-comp keys", keys );

            sortedDictionary = keys.reduce( ( sorted, itemName ) => 
            {
                const value = 
                {
                    name: itemName,
                    ...this.myDictionary[ itemName ]
                }

                sorted.push( value );

                return sorted;
            }, []);
        }

        console.log( "test-comp sortedDictionary", sortedDictionary );

        return sortedDictionary;
    }),



    actions:
    {
        addToObject()
        {
            set( this.myDictionary, `hello${this.counter}`, "42" );

            this.counter++;

            console.log( "test-comp addToObject", this.myDictionary );
        }
    }
});

In my mind, when I press the Add to Object button, my .hbs should rerender. However, it does not.

I am assuming this is because sortedDictionary is not recomputed and cannot detect that myDictionary has changed.

What is the correct solution to this problem?


Solution

  • In your ember computed function, only dependency is myDictionary. So computed will fire only theres a reference change to myDictionary object. You can tweak this by calling dictionary event change or adding another dependency which changes when firing the action (in your example, counter). If you are using counter as a dependency for the computed property, you have to use set function to trigger dependency change.

    In addition to that, hbs doesn't need to have this to get myDictionary since it uses related component as its context