dodgerogers747
dodgerogers747

Reputation: 3345

Ember.js - Run view related JS on all transitions and not just when the model changes

I have a "veteran" model with a copy attribute, this is a filename which represents a HTML page that is loaded via AJAX on the profile page. The HTML file contains some hardcoded ember links, e.g <a href="index.html#/veteran/1">Vet</a>. The majority of these links work when transitioning to other models, but when the model is the same, the below ajax function isn't called, and the HTML file isn't loaded into the DOM.

How can I make sure this code is run on every transition, instead of just when the model changes?

 App.VeteranView = Ember.View.extend({
    didInsertElement: function(){
        // Here we fetch the URL provided in the veteran model and load this data, which represents the main copy
        // of the particular vet into the attr div
        Ember.run.schedule('afterRender', this, function(){
            var ember = this.$().attr('id');
            $(document).ready(function() {
                var div = $('#' + ember).find(".attr");
                var url = div.data("id");
                $.get(url, function(data) {
                    div.html(data);
                    if ($(window).width() >= 767) {
                        $('.profile-info .columnizer').columnize({ columns: 2 });
                    }
                });
            });
        });
    }
});

Thanks to kingpin I managed to tweak his code, so that I can access dynamic DOM elements after every transition, even when the template stays the same. Setting the Ember run loop to "later" means that there's a 500ms delay, which seems to be enough time for everything to finish loading and transitioning.

App.VeteranView = Ember.View.extend({
watch: function(){
    Ember.run.later(this, this.ajaxLoad);
}.observes("controller"),

ajaxLoad: function(){
    // Here we fetch the URL provided in the veteran model
    // load this data, which represents the main copy
    // of the particular vet into the attr div
    var profileDiv = $(".profile-info");
    var url = profileDiv.find(".copy-url").text();
    if (url) {
        console.log("Rendering: " + url);
        $.get(url, function(data) {
            // First we'll load the data into the DOM
            profileDiv.find(".attr").html(data);

            // Now check if IE and browser width
            var ua = window.navigator.userAgent;
            var msie = ua.indexOf("MSIE ");

            if ($(window).width() >= 767 && msie > 0) {
                profileDiv.find('.columnizer').columnize({ columns: 2 });
            }
        });
    }   
}

});

Upvotes: 1

Views: 384

Answers (1)

Kingpin2k
Kingpin2k

Reputation: 47367

You have a couple of options.

1. Do it in setupController it's executed each time the model changes. Generally this isn't recommended for view magic, for that skip this option.

Setup Controller

App.FooRoute = Em.Route.extend({
  setupController: function(controller, model){
    this._super(controller, model);
    Em.run.scheduleOnce('afterRender', function(){
      alert('do it here');
    });
  }
});

2. Add an observers on the model reference, and when it changes go wild

View observing model

App.VeteranView = Ember.View.extend({
    watchStuff: function(){
        Ember.run.scheduleOnce('afterRender', this, this.doStuff);
    }.observes('controller.model').on('didInsertElement'),

    doStuff: function(){
      var el = this.$();
      if(el){
        el.hide(); // hahaha, get that user good
      }
    }
});

Example (check out the color view): http://emberjs.jsbin.com/OxIDiVU/674/edit

Upvotes: 2

Related Questions