Aurelia绑定-点击按钮返回查看模型
Aurelia binding - back to view model on button click
在Aurelia应用程序中,我有一个带有单个输入的"重命名"表单
<input ... value.bind="something.name" />
以及两个按钮:CCD_ 1和CCD_。
相同的something
对象已在其他控件中使用。因此,在单击Save
按钮之前,我不希望name
发生更改。
有没有一种很好的声明性方法来实现这一点,或者我必须将name
复制到另一个属性,然后在Save
触发器上将其复制回来?
您可以为编辑弹出窗口创建一个模型对象,并且仅在单击Save
时复制对列表中项目所做的编辑。下面是一个简化的示例:https://gist.run/?id=af3af031c5acc4c46407679f5ab1376b
查看
<template>
<ul>
<li repeat.for="person of people">${person.firstName} ${person.lastName} <button click.delegate="editPerson(person)">Edit</button></li>
</ul>
<div if.bind="editing">
First Name: <input type="name" value.bind="editModel.firstName" />
Last Name: <input type="name" value.bind="editModel.lastName" />
<button click.delegate="savePerson()">Save</button>
<button click.delegate="cancelEdit()">Cancel</button>
</div>
</template>
ViewModel
export class App {
editing = false;
people = [
{ firstName: 'John', lastName: 'Doe' },
{ firstName: 'Jane', lastName: 'Smith' },
{ firstName: 'Bob', lastName: 'Smith' }
];
editPerson(person) {
this.editing = true;
this.editObject = person;
this.editModel = Object.assign({},person);
}
savePerson() {
this.editing = false;
Object.assign(this.editObject, this.editModel);
this.editObject = null;
this.editModel = null;
}
cancelEdit() {
this.personBeingEdited = null;
this.editing = false;
}
}
我认为Ashley Grant的回答是一种非常清晰/直接的方法。我会选择这样的东西。既然您要求使用另一种方法,即使用更少的代码,那么就这样吧。。。。不确定它是否更好,这只是另一种方法,可能不太清楚。。。
https://gist.run?id=e931202307361d472c3e0ee4f523a833
视图模型具有一个名为editPerson
的属性,该属性表示当前正在编辑的人员。
app.js
export class App {
people = [
{ firstName: 'John', lastName: 'Doe' },
{ firstName: 'Jane', lastName: 'Smith' },
{ firstName: 'Bob', lastName: 'Smith' }
];
editPerson = null;
save() {
this.editPerson.firstName = this.firstNameInput.value;
this.editPerson.lastName = this.lastNameInput.value;
this.editPerson = null;
}
}
视图使用Save
0绑定将视图模型数据推送到输入中。对输入的编辑不会更新模型,因为绑定是单向的。提交表单时,将调用视图模型的save()
方法,该方法具有将输入值复制到模型中的逻辑。
app.html
<template>
<ul>
<li repeat.for="person of people">
${person.firstName} ${person.lastName}
<button click.delegate="editPerson = person">Edit</button>
</li>
</ul>
<form if.bind="editPerson" submit.delegate="save()">
<label>
First Name:
<input ref="firstNameInput" value.one-way="editPerson.firstName">
</label>
<label>
Last Name:
<input ref="lastNameInput" value.one-way="editPerson.lastName">
</label>
<button type="submit">Save</button>
<button type="button" click.delegate="editPerson = null">Cancel</button>
</form>
</template>
这里有一个使用自定义"可取消"绑定行为的替代方案。绑定会做以下事情:
- 拦截
updateSource
以将写入重定向到隐藏存储 - 侦听保存事件以将隐藏的存储写回原始源
"2"是通过遵守绑定上下文上的saved
属性的约定完成的。如果需要更大的灵活性,可以将属性名称作为参数传递给自定义绑定。
app.html
<template>
<require from='./cancellable'></require>
<div>
Name: ${name}
Age: ${age}
<button click.delegate="edit()">Edit</button>
</div>
<div if.bind="editing">
<h3>Cancellable edit</h3>
Name: <input value.bind="name & cancellable">
Age: <input value.bind="age & cancellable">
<div><button click.delegate="save()">Save</button>
<button click.delegate="cancel()">Cancel</button></div>
</div>
<div if.bind="editing">
<h3>Instant edit</h3>
Name: <input value.bind="name">
Age: <input value.bind="age">
</div>
</template>
app.js
export class App {
constructor() {
this.name = 'John';
this.age = 20;
this.editing = false;
this.saved = false;
}
edit() {
this.saved = false;
this.editing = true;
}
save() {
this.saved = true;
this.editing = false;
}
cancel() {
this.saved = false;
this.editing = false;
}
}
可取消.js
import {inject} from 'aurelia-dependency-injection';
import {BindingEngine} from 'aurelia-binding';
@inject(BindingEngine)
export class CancellableBindingBehavior {
constructor(bindingEngine) {
this.bindingEngine = bindingEngine;
}
bind(binding, scope) {
let value;
let modified = false;
let cancellable = {
originalUpdateSource: binding.updateSource,
originalUpdateTarget: binding.updateTarget,
};
// 1. Intercept "updateSource" to redirect write to a hidden value storage
binding.updateSource = (val) => {
value = val;
modified = true;
};
// 2. Intercept updateTarget" so that can observe change from original source
binding.updateTarget = (val) => {
value = val;
modified = false;
cancellable.originalUpdateTarget.call(binding, val);
}
// 3. Observe the "saved" event to copy back to original source
let bindingContext = scope.bindingContext;
cancellable.subscription = this.bindingEngine.propertyObserver(bindingContext, 'saved')
.subscribe((newValue, oldValue) => {
if (newValue && modified) {
cancellable.originalUpdateSource.call(binding, value);
}
});
binding.cancellable = cancellable;
}
unbind(binding, scope) {
binding.updateSource = binding.cancellable.originalUpdateSource;
binding.updateTarget = binding.cancellable.originalUpdateTarget;
binding.cancellable.subscription.dispose();
binding.cancellable = null;
}
}
Gist运行:https://gist.run/?id=2c7e40e88d1d3c18e9d2bca6be438b47
参考:内置的油门绑定行为
我所做的是制作一个我想要编辑的对象的副本,然后将其绑定到视图,当我单击保存时,我会将编辑的对象与我的原始对象"合并",以便将更改反映在其他控件中。
所以我编辑的ViewModel看起来是这样的:
activate(existingUser: User) {
let userCopy: User = JSON.parse(JSON.stringify(existingUser));
}
在我看来,然后我使用userCopy
对象来绑定属性。当我点击保存时,我会执行以下操作:
let indexOfUser = this.users.indexOf(existingUser);
Object.assign(this.users[indexOfUser], userCopy);
我简化了一些代码,因为在我的用例中,我使用的是一个对话框,该对话框将editedUser返回到不同的ViewModel,而ViewModel保存用户列表等。
- Angular,函数在(模型)工厂中返回值
- 无法在mvc视图中使用ajax调用获取操作返回的模型对象列表
- Aurelia绑定-点击按钮返回查看模型
- 续集返回未定义的模型自定义方法
- “渲染骨干模型视图”返回未定义的结果
- Node.js应用程序中从模型层异步返回数据
- Ember.js返回相同的模型
- 保存模型返回错误
- Ember.js:路由返回多个模型,包括一个promise,给出错误
- 在控制器中将 ng 模型值返回为空的指令
- 在视图模型中使用 MVC 视图返回 JsonResult 数据
- 挖空映射对象未由杜兰达尔视图模型返回
- 在我的情况下,ng 模型返回未定义
- Knockout视图模型返回函数(如何?)
- 从AngularJS$scope ng模型返回对象
- 基于User的客户模型返回基于userId而不是customerId的FK属性
- 需要余烬模型返回数组承诺而不是对象
- 如何在 AngularJS 中将数据异步从模型返回到控制器
- Ember JS -无法循环从模型返回的数组,即使它是一个数组
- 从骨干模型返回承诺