Ember嵌套数组属性可观察

时间:2013-11-27 16:00:14

标签: ember.js

在ember中设置嵌套数组上的属性observable时,不会通知我的属性。

size: function(){
      var result = "no size";

      this.get('data.properties').forEach(function (g) {
        if (g.group == "style") {
            g.items.forEach(function (p) {
                if (p.id == 'size') result = p.computedValue();
            });
        }
      });

    console.log(result);

    return result;
}.property('data.properties.@each.items.@each.value')

在此SO接受的答案中:https://stackoverflow.com/a/9381152/2068563 它说这应该有效。

但对我来说,这个预言只在init计算。 这是小提琴:http://jsfiddle.net/jmorvan/eVWfj/

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

好的,解决方法是将observable更新的计算属性链接到这样的事件:

App.groupObj = Ember.Object.extend({
    group: "style",
    name: "Style",
    _changed: 0,
    changed: function (key, value) {
        if (value) {
            this.set('_changed', value);
        }
        return this.get('_changed');
    }.property(),
    itemChanged: function () {
        this.set('changed', +new Date());
        console.log('item changed!');
    }.observes('items.@each.val'),

    items: []
});

App.itemObj = Ember.Object.extend({
    _val: 6,
    id: null,
    name: null,
    group: null,
    fieldType: null,
    val: function (key, value) {
        if (value) {
            this.set('_val', value);
        }

        return this.get('_val');
    }.property(),
    computedValue: function () {
        return this.val;
    }
});

基本上,grouo对象侦听项目的val属性上的任何操作并更新自己更改的属性。我这样做可以做到:

size: function(){
      var result = "no size";

      this.get('data.properties').forEach(function (g) {
        if (g.group == "style") {
            g.items.forEach(function (p) {
                if (p.id == 'size') result = p.computedValue();
            });
        }
      });

    console.log(result);

    return result;
}.property('data.properties.@each.changed')

我想我的第一个miastake是认为ember神奇地在我的嵌套对象上拾取更改。

我还认为链接计算属性会起作用,这显然没有! (为什么?)

更新的小提琴:http://jsfiddle.net/jmorvan/LEyCD/

修改

由于在每个对象上实现的时间很长,因此我使用基于选择器的observable创建了自己的对象。

    App.changeAwareArray = Ember.ArrayProxy.extend({
    init: function () {

        this.set('content', []);
        this._super();
        if (!this.get('changeSelector')) this.set('changeSelector', '_changed');

        this.addObserver('content.@each.' + this.get('changeSelector'), this.handleChange);
    },
        _changed: null,
    handleChange: function () {
        this.set('_changed', +new Date());
    }
});

App.changeAwareObject = Ember.Object.extend({
init: function () {
        this._super();
        if (!this.get('changeSelector')) this.set('changeSelector', '_changed');

        this.addObserver(this.get('changeSelector'), this.handleChange);
    },
        _changed: null,
    changed: function (key, value) {
        if (value) {
            this.set('_changed', value);
        }
        return this.get('_changed');
    }.property(),
    handleChange: function () {
        this.set('_changed', +new Date());
    }
});

现在你可以将它们链接起来观察它们:

    App.groupObj = App.changeAwareObject.extend({
    changeSelector:'items._changed',
    group: "style",
    name: "Style",
    items: App.changeAwareArray.create()
});

App.itemObj = Ember.Object.extend({
    _val: 6,
    _changed: null,
    id: null,
    name: null,
    group: null,
    fieldType: null,
    val: function (key, value) {
        if (value) {
            this.set('_val', value);
            this.set('_changed', +new Date());
        }
        return this.get('_val');
    }.property(),
    computedValue: function () {
        return this.val;
    }
});

获取视图/控制器中的数据:

    App.IndexView = Ember.View.extend({
    init: function () {
        this._super();
        //populate the Array
        this.data.properties.pushObject(createData());
    },
    elementId: "test",
    size: function () {
        var result = "no size";

        this.get('data.properties').forEach(function (g) {
            if (g.group == "style") {
                g.items.forEach(function (p) {
                    if (p.id == 'size') result = p.computedValue();
                });
            }
        });

        return result;
    }.property('data.properties._changed'),
    offset: function () {
        var result = "no offset";

        this.get('data.properties').forEach(function (g) {
            if (g.group == "style") {
                g.items.forEach(function (p) {
                    if (p.id == 'offset') result = p.computedValue();
                });
            }
        });

        return result;
    }.property('data.properties._changed'),
    data:{
        name: "base",
        properties: App.changeAwareArray.create()
    }
});

你可以在这里找到一个工作小提琴:http://jsfiddle.net/jmorvan/VRVac/