【问题标题】:Ajax added HTML elements added after ko.applyBindings not binding with knockoutjsAjax 添加了在 ko.applyBindings 之后添加的 HTML 元素未与 knockoutjs 绑定
【发布时间】:2013-10-02 14:34:57
【问题描述】:

我有一个使用 KnockoutJs(版本 2.3.0)的 ASP.NET MVC 4 视图。页面加载得很好,任何具有 data-bind 属性的 Existing 元素都可以按预期使用 KnockoutJs。问题是,如果我将 HTML 添加到包含 data-bind 的页面中,该页面已经包含在已绑定的 ViewModel 中的可观察对象,即使它具有正确的数据绑定属性。通过 Ajax 添加的 HTML 是 MVC PartialView。

HTML(开始)

<input type="text" id="FullName" data-bind="value: FullName" />    
<input type="text" id="Units" data-bind="value: Price" />
<input type="text" id="Price" data-bind="value: Units" />

<div id="AdditionalData"></div>

KO 视图模型

var ViewModel = function() {
    var self = this;
    self.FullName = ko.observable('Bob');
    self.Units = ko.observable(@Model.Units);
    self.Price = ko.observable(@Model.Price);
    self.SomeValue = ko.observable();
    self.CalculatedCost = ko.computed(function() {
       return self.Units * self.Price;
    };
};

ko.applyBindings(new ViewModel());

AJAX(在 .js 文件中)

APP.GetPartialView = function () {
    var _formValues = $("form#MyForm").serializeArray();
    var _url = $Url.resolve("~/Shared/_PartialViewName/?" + $.param(_formValues));
        function _success(html) {
            $("#AdditionalData").html(html);
        };

    $.ajax({
        url: _url,
        data: _formValues,
        cache: false,
        dataType: "html",
        success: _success
     });
};

MVC 控制器:PartialViewResult

[HttpGet]
public virtual PartialViewResult _PartialViewName(AccountViewModel model)
{
    return PartialView(model);
}  

MVC PartialView HTML

@model APP.AccountViewModel

<fieldset>
    @Html.Hidden("SomeValue", new { data_bind="value: SomeValue" })
    <ul>
       <li>
           @Html.LabelFor(m => m.FullName)
           <span data-bind="text: FullName"></span>
       </li>
       <li>
           @Html.LabelFor(m => m.CalculatedCost)
           <span data-bind="text: CalculatedCost"></span>
       </li>
    </ul>
</fieldset>

HTML(Ajax 调用后)

<input type="text" id="FullName" data-bind="value: FullName" />    
<input type="text" id="Units" data-bind="value: Price" />
<input type="text" id="Price" data-bind="value: Units" />

<div id="AdditionalData">
    <fieldset>
        <label for="SomeValue" data_bind="value: SomeValue" />
        <input type="hidden" id="SomeValue" name="SomeValue" data_bind="value: SomeValue" />
        <ul>
           <li>
               <label for="FullName" />
               <span data-bind="text: FullName"></span>
           </li>
           <li>
               <label for="CalculatedCost" />
               <span data-bind="text: CalculatedCost"></span>
          </li>
        </ul>
    </fieldset>
</div>

新添加的 html 将不会收到 FullName 的文本,并且计算成本的 ko 计算字段不会写入同名的 observable 的值。

那么,问题是如何告诉 Knockout 这些元素只是“迟到了”,但对于已经绑定的 ViewModel 可观察对象具有正确的数据绑定凭据?

已更新:我已更新上述问题的代码参考。

【问题讨论】:

  • 为什么不再次应用绑定?一般来说,您应该使用模板并使用 ko 绑定添加这个新标记。 github.com/ifandelse/Knockout.js-External-Template-Engine
  • @vittore 我的理解是每次 DOM 加载只能调用 ko.applyBindings() 一次。我已经尝试过了,它会引发错误,说明您不能多次这样做。关于模板:似乎模板更适合重复数据。上面的示例是我想要完成的简化版本,但我确实需要将模型数据从 Controller 传递到 PartialView Result 并且不太确定如何以 KO 模板方式重建它。与模板相反,似乎只需要“重新绑定”,但要接受建议。

标签: jquery ajax asp.net-mvc asp.net-mvc-4 knockout.js


【解决方案1】:

当淘汰赛出现时,接下来,innerHTml 所有这些东西都消失了。 问题是你以错误的方式去做。您想使用淘汰赛来摆脱这种片段注入。

上面的查看模型是你的模型:

    // This is the model
var Person = function(data) {
    var self = this;
    self.FullName = ko.observable(data.FullName);
    self.Address = ko.observable(data.Address);
};

// Your viewModel now uses Person to create People:
var ViewModel = function(){
    var self = this;
    self.People = ko.observableArray()
    self.addPeople = function(data){
        for( i = 0; i < data.length; i++ ){
            self.People.push(new Person(data[i]));
        }
    };
    self.addSam = function(){
        self.People.push(new Person({"FullName" : "Sam", "Address" : "Some address"}));
    };
    self.AddNewPerson = function(data){
        self.People.push(new Person(data));
    }
}

// Now I can create a new instance of VM:
var vm = new ViewModel();
vm.addPeople([{"FullName" : "Jon", "Address" : "Some address"},{"FullName" : "Pete", "Address" : "Some address"}]);

ko.applyBindings(vm);

vm.AddNewPerson({"FullName" : "Marry", "Address" : "Some address"})

您可以简单地通过调用内部方法或在代码中的其他地方调用它们来添加新元素

<ul data-bind="foreach: People">
    <li data-bind="text: FullName"></li>
</ul>

<a data-bind="click: addSam" href="#">Click me to add Sam</a>

【讨论】:

  • 我明白你在说什么,但我从 PartialView 添加的 HTML 的目的是进行计算,这些计算包含在 ko.computed 可观察对象中,该可观察对象依赖于主要可观察对象(两个可观察对象都已绑定在这一点——只是不是引用它们的最新 HTML 元素)。所以,我没有附加一个集合,只是显示一个新的 HTML 部分,其中包含所有单个值(即“1”行数据)的可观察对象(文本绑定到现有可观察对象)......并且在前提下这样做使用 MVC PartialViews。我看看能不能做个像Person这样的子模型看看
猜你喜欢
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
相关资源
最近更新 更多