在 Knockout.js 中从模型内部加载可观察量
Load observables from inside a model in Knockout.js
我有一个非常简单的项目视图模型。有一个用于编辑项目的点击处理程序,它应该将项目数据从服务器加载到模型中。单击处理程序称为 editProject。我想要的只是从服务器加载我的 observables。这种来自模型内部的方法不起作用。
this.editProject = function(){
$.getJSON("/projects/get_by_id", {
id: "7"
}).done(function(data){
ko.mapping.fromJSON(data[0], self);
});
};
我不确定哪里出了问题,因为您没有显示您的视图或整个视图模型。在调用 editProject
之前,您如何初始化视图模型?
这是一个在实际 project
之上的层中使用 editProject
方法的示例。
- 每个项目都有自己的视图模型,通过调用
ko.mapping.toJS
普通对象(来自服务器)创建
- 初始对象已具有所有属性,但有些没有值。
- 在 ajax 请求的成功回调中,通过将其作为第二个参数传递来更新单击的项目:
ko.mapping.fromJS(data, project)
。
如果 data
包含新属性,这些属性在 ko.applyBindings
时将不可用,因此不会被数据绑定。
const $ = fakeJQuery();
// The project should have its own viewmodel with initial data
// probably received from the server during first load
const myProjects =[
ko.mapping.fromJS({ id: "1", additionalInfo: null }),
ko.mapping.fromJS({ id: "7", additionalInfo: null })
];
const ViewModel = function() {
this.projects = ko.observableArray(
myProjects
);
// Take the project to edit as an argument
this.editProject = function(project) {
$.getJSON("/projects/get_by_id", project)
.done(function(data) {
// Because we have access to the clicked project,
// we map to its existing viewmodel using `fromJS`
ko.mapping.fromJS(data, project);
});
};
};
ko.applyBindings(new ViewModel());
// Mocks
function fakeJQuery() {
return {
// Mock ajax request
getJSON: function(url, opts) {
let done = () => true;
setTimeout(function() {
// Test data to indicate an update:
done({
id: opts.id(),
additionalInfo: "Test " + opts.id()
});
}, 1000);
return {
done: cb => done = cb
};
}
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<ul data-bind="foreach: projects">
<li>
<code data-bind="text: 'id: ' + id()"></code>
<button data-bind="click: $parent.editProject">edit</button>
<p>
Info:
<strong data-bind="text: additionalInfo"></strong>
<em data-bind="visible: !additionalInfo()">not loaded</em>
</p>
</li>
</ul>
我有一个非常简单的项目视图模型。有一个用于编辑项目的点击处理程序,它应该将项目数据从服务器加载到模型中。单击处理程序称为 editProject。我想要的只是从服务器加载我的 observables。这种来自模型内部的方法不起作用。
this.editProject = function(){
$.getJSON("/projects/get_by_id", {
id: "7"
}).done(function(data){
ko.mapping.fromJSON(data[0], self);
});
};
我不确定哪里出了问题,因为您没有显示您的视图或整个视图模型。在调用 editProject
之前,您如何初始化视图模型?
这是一个在实际 project
之上的层中使用 editProject
方法的示例。
- 每个项目都有自己的视图模型,通过调用
ko.mapping.toJS
普通对象(来自服务器)创建 - 初始对象已具有所有属性,但有些没有值。
- 在 ajax 请求的成功回调中,通过将其作为第二个参数传递来更新单击的项目:
ko.mapping.fromJS(data, project)
。
如果 data
包含新属性,这些属性在 ko.applyBindings
时将不可用,因此不会被数据绑定。
const $ = fakeJQuery();
// The project should have its own viewmodel with initial data
// probably received from the server during first load
const myProjects =[
ko.mapping.fromJS({ id: "1", additionalInfo: null }),
ko.mapping.fromJS({ id: "7", additionalInfo: null })
];
const ViewModel = function() {
this.projects = ko.observableArray(
myProjects
);
// Take the project to edit as an argument
this.editProject = function(project) {
$.getJSON("/projects/get_by_id", project)
.done(function(data) {
// Because we have access to the clicked project,
// we map to its existing viewmodel using `fromJS`
ko.mapping.fromJS(data, project);
});
};
};
ko.applyBindings(new ViewModel());
// Mocks
function fakeJQuery() {
return {
// Mock ajax request
getJSON: function(url, opts) {
let done = () => true;
setTimeout(function() {
// Test data to indicate an update:
done({
id: opts.id(),
additionalInfo: "Test " + opts.id()
});
}, 1000);
return {
done: cb => done = cb
};
}
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<ul data-bind="foreach: projects">
<li>
<code data-bind="text: 'id: ' + id()"></code>
<button data-bind="click: $parent.editProject">edit</button>
<p>
Info:
<strong data-bind="text: additionalInfo"></strong>
<em data-bind="visible: !additionalInfo()">not loaded</em>
</p>
</li>
</ul>