【问题标题】:Ember Js computed property in component fails when observing object property in service观察服务中的对象属性时,组件中的 Ember Js 计算属性失败
【发布时间】:2017-05-27 18:38:22
【问题描述】:

在 Ember js 中有一个有趣的问题。

下面是组件advanced-search/component.js,具有两个计算属性roomTyperoom,依赖于服务services/advanced-searchqueryObj.{roomId,roomTypeId} 对象属性。

当从模板中选择一个选项时,roomType 计算属性会触发并正确更新模板。然而,有趣的是,当从模板中选择房间时,room 计算属性无法触发。我通过在 room 计算属性中放置 console.log('checking room computed fired') 来验证这一点。

为了进一步探索这个异常,我做了以下事情:

  1. 我取消了您在init 方法中看到的代码的注释,该方法设置了填充房间列表下拉列表的rooms 数组,并在最初设置@987654333 的setRoomType 操作方法内的操作哈希中注释了代码@ 大批。在这些更改之后,room 计算属性会正确触发并更新模板。
  2. 我注意到this.get('store).findAll('roomType') 返回的数组导致roomType 计算属性正确触发并更新模板,因此我尝试将setRoomType 中对rooms 的调用从roomType.get('rooms') 更改为@ 987654340@ 看看它是否也导致room 计算属性正确触发,但它仍然NOT 触发room 计算属性。因此,我得出结论,roomTyperoom 计算属性只有在组件的 init 方法中设置了它们的下拉列表数组时才能正确触发和更新模板。

高级搜索/component.js

export default Ember.Component.extend({
advancedSearch: Ember.inject.service('advanced-search'),
queryObj: Ember.computed.alias('advancedSearch.queryObj'),
init() {
    this._super(...arguments);
    // I believe because the 'roomTypes` array is set in this init method, the 'roomType' computed property fires correctly and updates the template
    this.get('store').findAll('roomtype').then((roomTypes) => {
        this.set('roomTypes', roomTypes);
    });
    // When the 'rooms' array is also initialized here, the 'room' computed property fires successfully on 'room' selection from the dropdown and updates the template
    // this.get('store').findAll('room').then((rooms) => {
    //     this.set('rooms', rooms);
    // });
},
roomTypes: [],
roomType: Ember.computed('queryObj.{roomTypeId}', function() {
    var that = this;
    return this.get('roomTypes').find(function(roomType) {
        return that.get('queryObj').roomTypeId === roomType.id;
    });
}),
rooms: [],
room: Ember.computed('queryObj.{roomId}', function() {
    console.log('checking room computed fired')
    var that = this;
    return this.get('rooms').find(function(room) {
        return that.get('queryObj').roomId === room.id;
    });
}),

actions: {
    setRoomType(roomType) {         
        this.get('advancedSearch').setRoomType(roomType);
        this.set('room', null);
        if (roomType) {
            // When rooms array initialized from here  the room computed property fails to fire on room selection from drop down
            roomType.get('rooms').then((rooms) => {
                this.set('rooms', rooms);
            });
        } else {
            this.set('rooms', null);
        }

    },
    setRoom(room) {
        this.get('advancedSearch').setRoom(room);
    }
}});

下面是服务代码:

服务/高级搜索

export default Ember.Service.extend({
queryObj: {},
setRoomType(roomType) {
    this.set('queryObj.roomTypeId', roomType.id);
},
setRoom(room) {
    this.set('queryObj.roomId', room.id);
}});

下面是组件模板:

高级搜索/template.hbs

<div class="col-md-12">
  <div class="box box-primary">
    <div class="box-header with-border">
      <h3>Advanced Search</h3>
    </div>
    <div class="box-body">
      <div class="row">
        <div class="col-md-2">
          {{#power-select placeholder="Room type" allowClear=true selected=roomType options=roomTypes onchange=(action "setRoomType") as |roomType| }} {{roomType.name}} {{/power-select}}
        </div>
        <div class="col-md-2">
          {{#power-select placeholder="Room No" allowClear=true selected=room options=rooms onchange=(action "setRoom") as |room| }} {{room.name}} {{/power-select}}
        </div>
      </div>
    </div>
    <!-- /.box-body -->
  </div>
  <!-- /.box -->
</div>

注意:我希望通过“roomType”模型的名为“rooms”的关系属性从操作方法“setRoomType”设置“rooms”属性,以便始终根据选择的“roomType”过滤房间.

我们将不胜感激。

Ember 版本:

  • Ember Inspector 2.0.4
  • Ember 2.8.2
  • Ember 数据 2.9.0
  • jQuery 3.1.1
  • Ember 简单身份验证 1.1.0

【问题讨论】:

    标签: javascript ember.js


    【解决方案1】:

    你不应该设置像this.set('room', null);这样的计算属性。我猜这行代码是罪魁祸首。一旦你设置了这样的计算属性,那么这个计算属性将不会再次触发。

    您可能需要的是 room 带有 get 和 set 的计算属性。参考setting computed properties guide

    test:Ember.computed('dependantKey',{
        get(key){
          return 'result';
        },
        set(key,value){
          return value;
        }
      })
    

    【讨论】:

    • 是的,这对我来说也很突出。你可能最好不要在计算属性上使用 set ,而是改变计算属性所依赖的任何东西。这让事情变得可预测
    • 太棒了。我马上就看到了你提到它。我不敢相信我花了 4 个小时在看似如此明显的事情上。实际上,我设置了错误的属性,错误的值。我打算设置的是this.set('rooms', []);。现在它可以完美运行,因为 rooms 属性不是计算属性,它是设置房间列表的属性。谢谢大家!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    • 2016-04-15
    • 1970-01-01
    • 2015-04-28
    相关资源
    最近更新 更多