Regular Javascript Data Objects in Controllers - Best Practice


#1

Hi.

In my Ember controller I have created a regular Javascript object to store the non-persistent data associated with the current route, e.g. The modal buttons, form fields, tabs etc. These values are passed to the modal component. It looks something like this:

modals: {
    myModal: {
        buttons: [
            {text: 'MyButton', action: 'myAction' disabled: true},
            {text: 'MyOtherButton', action: 'myOtherAction' disabled: true}
        ],
        tabs: {
            {name: 'myTab', colour: 'red'},
            {name: 'myOtherTab', colour: 'green'}
        },
        fields: {
            dropdownContact: {
                value: 'primaryContact',
                options: [
                    {text: 'Primary Contact', value: 'primaryContact'},
                    {text: 'Secondary Contact', value: 'secondaryContact'}
                ]
            }
        }
    }
}

The problem I have is that some of the attributes within this object need setting dynamically depending on the value of computed properties and other values outside the object. I cannot use the “this.get(‘myAttribute’)” functionality because this object is at the top-level. So, I tried making this object the return value of a computed property that depended upon the model, e.g:

modals: Ember.computed('model', function() {
    return {***the object above***};
});

However, this causes problems with the stack being exceeded. I tried regular functions but there were issues with this too.

Essentially, I’d just like to know if I’m overcomplicating things here and if so what is the recommended way of creating data objects that can be initialized with dynamic values from elsewhere in the controller, e.g. this.get(‘myAttribute’)?

Any pointers would be greatly appreciated.

Thanks.


#2

Ok, so having done some research on the Web and seeing the code used by others it seems that the best approach is not to use all-encompassing JS objects for data. Breaking up your non-persistent data in to its own controller properties, computed properties and aliases seems to be the “happy path”. This helps prevent infinite loops caused by calling methods which then cause computed properties to re-calculate causing the same methods to be called again (stack exceeded error).

I looked at my JS object and decided to take all of the static properties and hard code them in to templates/component calls, e.g. I set the header of a modal component as a “header” attribute when calling it rather than using property from the controller as this was unnecessary. I did keep some of the static properties in controller properties where they were part of a small JS object that was passed to a component as an attribute for the component to generate its template from, e.g.

contactMerchantModalTabs: {
    call: {name: 'call', text: 'Call', active: false},
    email: {name: 'email', text: 'Email', active: false}
},

but otherwise static properties became hard-coded.

I then took all of the dynamic properties and split them up in to their own separate properties with the exception of form field options/values which I grouped under their own JS object. This made it much easier to get and set values and made the code easier to read as there were no long get calls to access deeply nested JS object properties, e.g.

this.get('myObject.firstLevelProperty.secondLevelProperty.thirdLevelProperty');

I’m now happy with my streamlined controller and templates and things are working more predictably now too!

If anyone can spot any issues with my approach I’d be glad to hear about them as I am still getting to grips with Ember and have much to learn!