EmberJS: observe parent route's model and change child route's model accordingly

梦想与她 提交于 2019-12-11 11:00:45

问题


I'm setting up a master-detail interface with two routes. The parent route houses an EventSource stream that regularly updates it's model.

I'm trying to make it so when the parent route's model suffers a change on any of its items, if the current detail view is displaying any of the changed items then it should be updated.

I'm currently trying to make a binding on the receptor route to receptores's controller's model and observing that:

Edited per blessenm's suggestions:

var App = Ember.Application.create({
    rootElement: '#content'
});

App.Router.map(function() {
    this.resource('receptores', {path: '/'}, function() {
        this.resource('receptor', {path: ':user_id'});
    });
});

App.ReceptoresRoute = Ember.Route.extend({
    model: function() {
        var deferredData = Ember.Deferred.create();
        var data = [];
        var sse = new EventSource('/monitoreo/receptores/push');
        sse.addEventListener('update-receptores', function(e) {
            var receptores = JSON.parse(e.data);
            receptores.forEach(function(r) {
                var item = data.findBy('id', r.id);
                if (typeof(item) != 'undefined') {
                    data.replace(data.indexOf(item), 1, [r]);
                } else {
                    data.pushObject(r);
                }
            });
            deferredData.resolve(data);
        });
        sse.addEventListener('ping', function(e) {
            console.log('ping');
        });
        return deferredData;
    }
});

App.ReceptorRoute = Ember.Route.extend({
    model: function(params) {
        return this.modelFor('receptores').findBy('id', params.user_id);
    }
});

App.ReceptorController = Ember.ObjectController.extend({
    needs: ['receptores'],
    parentModelBinding: Ember.Binding.oneWay('controllers.receptores.model'),
    parentModelDidChange: function() { // never fires
        console.log('changed');
        this.set('model', this.modelFor('receptores').findBy('id', this.get('model').user_id));
    }.observes('parentModel')
});

This is what I have so far. What happens is parentModelDidChange never fires. Using chrome I inspected receptor's controller and a parentModel property is never set, which I interpret as the binding not working.

I have a feeling I need to set up the model changes on the receptores controller and not its route, but when I try the following I get the exception Assertion Failed: The value that #each loops over must be an Array. You passed <Ember.Deferred:ember338>:

App.ReceptoresRoute = Ember.Route.extend({
    setupController: function(controller) {
        // same as the previous model hook
        ...
        controller.set('model', deferredData);
    }
});

My current solution. I took the EventSource out of the receptores route and placed it in the global scope. Added an event listener to it from the receptor controller's init hook.

It seems to me that this should not be necessary. There should be a way to bind the child controller's model to the corresponding item in the parent route's array model. Changes on that source item should be reflected on the child immediately, but I guess that depends on the application's design as well.

var App = Ember.Application.create({
    rootElement: '#content'
});

App.Router.map(function() {
    this.resource('receptores', {path: '/'}, function() {
        this.resource('receptor', {path: ':user_id'});
    });
});

var sse = new EventSource('/monitoreo/receptores/push');

App.ReceptoresRoute = Ember.Route.extend({
    model: function() {
        var deferredData = Ember.Deferred.create();
        var data = [];
        sse.addEventListener('update-receptores', function(e) {
            var receptores = JSON.parse(e.data);
            receptores.forEach(function(r) {
                var item = data.findBy('id', r.id);
                if (typeof(item) != 'undefined') {
                    data.replace(data.indexOf(item), 1, [r]);
                } else {
                    data.pushObject(r);
                }
            });
            deferredData.resolve(data);
        });
        sse.addEventListener('ping', function(e) {
            console.log('ping');
        });
        return deferredData;
    }
});

App.ReceptorRoute = Ember.Route.extend({
    model: function(params) {
        return this.modelFor('receptores').findBy('id', params.user_id);
    }
});

App.ReceptorController = Ember.ObjectController.extend({
    init: function() {
        var self = this;
        sse.addEventListener('update-receptores', function(e) {
            var current_id = self.get('model').id;
            JSON.parse(e.data).forEach(function(r) {
                if (r.id == current_id) {
                    self.set('model', r);
                }
            });
        });
    }
});

来源:https://stackoverflow.com/questions/23841178/emberjs-observe-parent-routes-model-and-change-child-routes-model-accordingly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!