Best practice in accessing elements in views - run later?


#1

In our application we have a number of views which are created on demand. These are mostly posting or editing forms which don’t exist until accessed. In 2 cases we’re attaching a date/time picker plugin to input fields within these forms. The problem we’re having is that Ember doesn’t create the input field “in time” for the plugin to attach itself.

        Ember.run.later(this, function() {

            // focus the input field
            $view.find('textarea').focus();

            // init date picker
            utils.initDatePicker(dateField, createWithinSelector);

            // init time picker
            utils.initTimePicker(timeField, createWithinSelector);

            // Set the current profile
            this.send('setActiveProfile', this.get('controller.controllers.profiles').objectAt(0));
        }, 250);

What we’ve been forced to do is to use the Ember.run method call to pause for a split second (usually 100-250 ms) so that Ember has time to finish its business. This works well, but leaves a bad taste in my mouth. I’m wondering how others are managing this sort of process. Is the run loop a necessary evil in this case, or is there a better way to manage this process?


#2

You can handle element bindings and such under the Ember View or Component via didInsertElement event. Also be sure to “unbind” them with the willDestroyElement event.

App.WhateverView = Ember.View.extend({
    bindPickers: function(){
        var $view = this.$();

        // focus on the input field
        $view.find('textarea').focus();

        // init date picker
        utils.initDatePicker(dateField, createWithinSelector);

        // init time picker
        utils.initTimePicker(timeField, createWithinSelector);

        // Set the current profile
        this.send('setActiveProfile', this.get('controller.controllers.profiles').objectAt(0));

    }.on('didInsertElement'),

    unbindPickers: function(){
        // anything you would typically do with .off() and such
    }.on('willDestroyElement')

}); // end View

#3

Hrm. Looks like the View apparently renders when the page loads, and not when it’s called.