Ember.js更新模型属性

问题描述 投票:1回答:1

我对ember.js的工作方式没有最好的了解。我目前正在更新每个所有者使用多选复选框选中的称为功能(字符串数组)的属性。到目前为止,除了更新的功能属性未保存之外,其他所有内容似乎都可以正常工作。当我单击复选框时,它会更新multi-select-checkboxes组件中的选定计算属性。我以为如果将选择的model.owner.features传递给组件,则当组件发生更改时,它将直接更新模型。

(function() {
  const { shroud } = Sw.Lib.Decorators;

  Sw.FranchisorNewAnalyticsConnectionsUsersRoute = Ember.Route.extend({
    currentFranchisorService: Ember.inject.service('currentFranchisor'),

    @shroud
    model({ account_id }) {
      console.log("load model in route")
      return Ember.RSVP.hash({
        account: this.get('store').find('account', account_id),
        owners: Sw.AccountOwner.fetch(account_id),
        newAccountOwner: Sw.AccountOwner.NewAccountOwner.create({ accountID: account_id }),
      });
    },

    actions: {
      @shroud
      accountOwnersChanged() {
        this.refresh();
      },

      close() {
        this.transitionTo('franchisor.newAnalytics.connections');
      },
    },
  });
})();

用户控制器:

(function() {
  const { shroud, on, observer } = Sw.Lib.Decorators;
  Sw.FranchisorNewAnalyticsConnectionsUsersController = Ember.Controller.extend(Sw.FranchisorControllerMixin, {
    isAddingUser: false,

    adminOptions: [{
      label: 'Employee Advocacy',
      value: 'employee advocacy'
    }, {
      label: 'Second Feature',
      value: 'other'
    }, {
      label: 'Can edit users?',
      value: 'edit_users'
    }],

  });
})();

users.handlebars

 {{#each model.owners as |owner|}}
   <tr
    <td>
     {{owner.name}}
    </td>
    <td>
     {{owner.email}}
    </td>
    <td>{{if owner.confirmedAt 'Yes' 'No'}}</td>
    <td>
      {{log 'owner.features' owner.features}}
      {{multi-select-checkboxes 
         options=adminOptions 
         selected=owner.features
         owner=owner
         model=model
       }}
     </td>
     <td>
       <button class="btn light-red-button" 
         {{action "remove" owner}}>
         Remove
       </button>
     </td>
   </tr>
 {{/each}}

multi-select-checkboxes.handlebar:

{{#each checkboxes as |checkbox|}}
  <p>
    <label>
      {{input type='checkbox' checked=checkbox.isChecked}}
      {{checkbox.label}}
    </label>
  </p>
{{/each}}

multi_select_checkboxes.jsx:

 // Each available option becomes an instance of a "MultiSelectCheckbox" object.
var MultiSelectCheckbox = Ember.Object.extend({
  label: 'label',
  value: 'value',
  isChecked: false,

  changeValue: function () { },
  onIsCheckedChanged: Ember.observer('isChecked', function () {
    var fn = (this.get('isChecked') === true) ? 'pushObject' : 'removeObject';
    this.get('changeValue').call(this, fn, this.get('value'));
  })
});

Sw.MultiSelectCheckboxesComponent = Ember.Component.extend({
  labelProperty: 'label',
  valueProperty: 'value',
  // The list of available options.
  options: [],
  // The collection of selected options. This should be a property on
  // a model. It should be a simple array of strings.
  selected: [],
  owner: null,
  model: null,
  checkboxes: Ember.computed('options', function () {
      console.log("CHECKBOXES", this.get('model'))
    var _this = this;
    var labelProperty = this.get('labelProperty');
    var valueProperty = this.get('valueProperty');
    var selected = this.get('selected'); 
    var model = this.get('model'); 
    return this.get('options').map(function (opt) {
      var label = opt[labelProperty];
      var value = opt[valueProperty];
      var isChecked = selected.contains(value);
      return MultiSelectCheckbox.create({
        label: label,
        value: value,
        isChecked: isChecked,
        model: model,
        changeValue: function (fn, value, model) {
          _this.get('selected')[fn](value);
          console.log("model in middle", this.get('model'))
          this.get('model').save();
        }
      });
    });
  }),
  actions: {
    amountChanged() {
      const model = this.get(this, 'model');
      this.sendAction('amountChanged', model); 
    }
  }
});
ember.js
1个回答
0
投票

似乎您对我有相当不错的理解!我认为您的实现只是在这里或那里丢失了一件东西,可能比必须的要复杂一些。

这里是Twiddle,可以满足您的要求。我为模型attrs命名了该属性,以避免由于attributes在某些模型方法(例如rollbackAttributes()changedAttributes())中发挥作用而引起的混淆。

一些注意事项:

  1. 创建复选框对象列表时,无需指定changeValue函数。 onIsCheckedChanged观察者应负责更新模型的属性。在多选复选框中映射options时,只需将要更新的模型或其属性(字符串数组)传递到每个复选框即可:
  2. return Checkbox.create({
      label: option.label,
      value: option.value,
      attributes: this.get('owner.attrs') // this array will be updated by the Checkbox
    });
    
  1. 如果您检索的模型在此数组中没有任何数据,Ember Data会将属性保留为undefined,因此直接在数组上进行更新将导致错误(例如cannot read property 'pushObject' of undefined),因此确保在该组件允许用户更新值之前,将属性设置为数组。

  2. 观察者将触发synchronously,因此将它包装在Ember.run.once()中可能是值得的(不确定您将对该组件/模型进行什么操作,因此为完整性起见,请注意这一点。)]]

  3. 如果要自动在模型上保存更改,则需要在更新后在模型上调用.save()。在这种情况下,我会将模型传递到每个复选框,并在进行更改后调用save。

© www.soinside.com 2019 - 2024. All rights reserved.