2

I have an ASP.NET MVC 4 View that uses KnockoutJs (version 2.3.0). The page loads just fine and any Existing elements with the data-bind attribute work as expected with KnockoutJs. The problem is that if I add HTML to the page that contains a data-bind for an observable already contained within the ViewModel that has been bound, it seems like it isn't subscribed even though it has the correct data-bind attribute. The HTML being added via Ajax is a MVC PartialView.

HTML (Starting)

<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 ViewModel

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 (within a .js file)

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 Controller: 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 (After Ajax Call)

<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>

The newly added html will not receive the text for the FullName and the ko computed field for Calculated Cost will not write the value for the observable of the same name.

So, the question is how to tell Knockout that these elements are just "late to the party" but have the correct data-bind credentials for ViewModel observables that are already bound?

Updated: I have updated the code references above for the question.

4

1 回答 1

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>
于 2013-09-26T15:48:30.593 回答