Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global variables in Ember

What would be the appropriate method for storing a global variable in Ember? For example, I have a User model in Ember, but I'd always like to know which specific instance of that model (including its id, name, email, etc) corresponds to the currently logged-in user.

Should I be storing this within Ember somehow? Or is it better to just attach a JS variable to the window object (e.g. window.currentUserId = 1;) and use that?

like image 600
NudeCanalTroll Avatar asked Feb 12 '13 23:02

NudeCanalTroll


1 Answers

Disclaimer: All the techniques shown below are my experience with EmberJS for the past few months, plus some discussions with my colleagues. Anything incorrect, please raise your voice. We are all in the learning phase (and ember.js doc sucks to the maxxx, so be kind ;)

Currently there are two developers in my work place that are using Ember.js. We came to a conclusion that storing global variables in the global ApplicationController is much better than storing in the application namespace. This is because the retrieval of this value could be very messy if it's stored in the application namespace. And this works well in closure too, and hence make the global namespace clean (and relatively hack free). You don't want your user to do App.set to mess with the variable right?

This is based on 1.0.0 pre-4.

Considering you have this currentUserId global variable

  1. Storing in the namespace. jsFiddle demo

    (function() {
    
        function r() {
            return Math.round(Math.random()*999);
        }
    
        var MyApp = Ember.Application.create({
            currentUserId: null,
            ready: function() {
                //demo purpose.
                this.set('currentUserId', r());
            },
            rootElement: '#demo'
        });
        MyApp.ApplicationView = Ember.View.extend({
            templateName: 'application-view',
    
            //Direct child view
            innerView: Ember.View.extend({
                templateName: 'inner-view',
                setValue: function() {
                    this.set('controller.namespace.currentUserId', r());
                }
            }),
    
            //Direct child view, but with a controller attached
            innerViewWithController: Ember.View.extend({
                controller: Ember.Controller.create(),
                templateName: 'inner-view-with-controller',
                setValue: function() {
                    this.set('parentView.controller.namespace.currentUserId', r());
                }
            }),
            getValue: function() {
                alert(this.get('controller.namespace.currentUserId'));
            },
            setValue: function() {
                this.set('controller.namespace.currentUserId', r());
            }
        });
    })();
    
  2. vs Storing in global ApplicationController jsFiddle demo

    (function() {
    
        function r() {
            return Math.round(Math.random()*999);
        }
    
        var MyApp = Ember.Application.create({
            ApplicationController: Ember.Controller.extend({
                currentUserId: null,
                init: function() {
                    //demo purpose
                    this.set('currentUserId', r());
                }
            }),
            rootElement: '#demo'
        });
        MyApp.ApplicationView = Ember.View.extend({
            templateName: 'application-view',
    
            //Direct child view
            innerView: Ember.View.extend({
                templateName: 'inner-view',
                setValue: function() {
                    this.set('controller.currentUserId', r());
                }
            }),
    
            //Direct child view, but with a controller attached
            innerViewWithController: Ember.View.extend({
                controller: Ember.Controller.create(),
                templateName: 'inner-view-with-controller',
                setValue: function() {
                    this.set('parentView.controller.currentUserId', r());
                }
            }),
            getValue: function() {
                alert(this.get('controller.currentUserId'));
            },
            setValue: function() {
                this.set('controller.currentUserId', r());
            }
        });
    })();
    

Note that:

  1. If you chose to store in namespace, you will need to access it via the root controller all the time, so it's actually same as storing in the applicationController with an extra namespace keyword.

  2. If you chose to store it in root applicationController, for whatever views that descend from the applicationView, you can easily access the variable in your templates with {{variableName}} without any dot traversals. By default Ember.Js look for variables via controllers.

  3. In the worst case, if your internal view need to have their own controller, accessing the global variable via root controller (or namespace) is slightly more painful because controllers are not linked, you will need to traverse up your views until you see the root controller. In Ember.JS, all views, by default, will have a controller set, and by default, parent's controller. Which means if you never specify any controller, all descendant views are actually linked to root controller. To overcome this issue, you can do variable binding in the controller to easily solve the traversing ugliness.

I do not suggest you to put such an important variable in the global window object as it will be easily modified by the user (and raises any potential issues). Putting it in the global namespace in the ember application namespace reduces the potential issue but not if you make it global

My 2 cents ;)

like image 136
Lionel Chan Avatar answered Oct 18 '22 21:10

Lionel Chan