我对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);
}
}
});
似乎您对我有相当不错的理解!我认为您的实现只是在这里或那里丢失了一件东西,可能比必须的要复杂一些。
这里是Twiddle,可以满足您的要求。我为模型attrs
命名了该属性,以避免由于attributes
在某些模型方法(例如rollbackAttributes()
或changedAttributes()
)中发挥作用而引起的混淆。
一些注意事项:
changeValue
函数。 onIsCheckedChanged
观察者应负责更新模型的属性。在多选复选框中映射options
时,只需将要更新的模型或其属性(字符串数组)传递到每个复选框即可:return Checkbox.create({
label: option.label,
value: option.value,
attributes: this.get('owner.attrs') // this array will be updated by the Checkbox
});
如果您检索的模型在此数组中没有任何数据,Ember Data会将属性保留为undefined
,因此直接在数组上进行更新将导致错误(例如cannot read property 'pushObject' of undefined
),因此确保在该组件允许用户更新值之前,将属性设置为数组。
观察者将触发synchronously,因此将它包装在Ember.run.once()中可能是值得的(不确定您将对该组件/模型进行什么操作,因此为完整性起见,请注意这一点。)]]
如果要自动在模型上保存更改,则需要在更新后在模型上调用.save()
。在这种情况下,我会将模型传递到每个复选框,并在进行更改后调用save。