正如 Anh Bui 所建议的,我会在浏览器中动态创建它们。将applyBindings 与您在服务器端使用 ASP.net 创建的标记一起使用有点像 hack,这意味着您要对抗 Knockout,而不是使用它。
最好让 Knockout 负责实际创建表单。这意味着
- 仅向其提供创建每个 JSON 表单所需的数据
- 为表单标记创建 Knockout 模板
- 使用
forEach 绑定循环遍历数据
模板:
<script type="text/html" id="form-template">
<form action="/target-url">
<label for="user_name">What's your name?</label>
<input type="text" data-bind="value: user_name" name="user_name" />
<label for="user_location">Where are you from?</label>
<input type="text" data-bind="value: user_location" name="user_location" />
</form>
</script>
接下来,您将相关的表单数据输出为服务器端的 JSON 数组。我没用过ASP.net,所以这里只能给你伪代码:
<script type="application/javascript">
window.form_json_from_server = "
@foreach (var form in Model.AllForms.ToList())
{
// .. ASP.net JSON output magic goes here
}
";
</script>
这样你的标记的最终结果看起来像
<script type="application/javascript">
window.form_json_from_server = "[
{ user_name: "Foo1", user_location: "Bar1" },
{ user_name: "Foo2", user_location: "Bar2" },
{ user_name: "Foo3", user_location: "Bar3" }
]";
</script>
(请注意,JS 字符串不能包含换行符,我这里用换行符格式化,方便阅读)
现在我们将表单数据格式化为 JSON,保存在 Javascript 字符串中。接下来:您的 Knockout 视图模型:
var ViewModel = function ViewModel() {
var that = this,
raw_forms_object;
// we reconstitute our JSON string into a Javascript object
raw_forms_object = JSON.parse(window.form_json_from_server);
// this is where the objects made from our JSON will end up in
this.forms = ko.observableArray([]);
ko.utils.arrayForEach(raw_forms_object, function(f) {
// f contains one of our form objects, such as { user_name: "Foo1", user_location: "Bar1" }
// instead of adding f directly to the array, we make a new object in which the
// properties are observables
var form = {
user_name: ko.observable(f.user_name),
user_location: ko.observable(f.user_location),
};
// add our new form object to our observableArray
// make sure to use 'that', because 'this' is the scope of the arrayForEach callback we're in
that.forms.push(form);
});
}
现在我们的视图模型上有一个名为“forms”的 observableArray,其中包含我们的表单对象。我们使用forEach 绑定来创建与表单对象一样多的表单:
<div data-bind="template: { name: 'form-template', foreach: forms }"></div>
剩下的就是将我们的视图模型实例应用到页面:
ko.applyBindings( new ViewModel() );
如果你喜欢,你可以在这个可运行的代码 sn-p 中尝试一下:
var ViewModel = function ViewModel() {
var that = this,
raw_forms_object;
// we reconstitute our JSON string into a Javascript object
raw_forms_object = JSON.parse(window.form_json_from_server);
// this is where the objects made from our JSON will end up in
this.forms = ko.observableArray([]);
ko.utils.arrayForEach(raw_forms_object, function(f) {
// f contains one of our form objects, such as
// { user_name: "Foo1", user_location: "Bar1" }
// instead of adding f directly to the array, we make a new object in which the
// properties are observables
var form = {
user_name: ko.observable(f.user_name),
user_location: ko.observable(f.user_location),
};
// add our new form object to our observableArray
// make sure to use 'that', because 'this' is the scope
// of the arrayForEach callback we're in
that.forms.push(form);
});
}
ko.applyBindings( new ViewModel() );
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script type="text/html" id="form-template">
<form action="/target-url">
<label for="user_name">What's your name?</label>
<input type="text" data-bind="value: user_name" name="user_name" />
<label for="user_location">Where are you from?</label>
<input type="text" data-bind="value: user_location" name="user_location" />
</form>
</script>
<div data-bind="template: { name: 'form-template', foreach: forms }"></div>
<script type="application/javascript">
window.form_json_from_server = '[{"user_name": "Foo1","user_location": "Bar1"},{"user_name": "Foo2","user_location": "Bar2"},{"user_name": "Foo3","user_location": "Bar3"}]';
</script>