KnockoutJS - Observable Array of Observable objects

后端 未结 3 1309
清酒与你
清酒与你 2020-12-09 07:59

I would like to display an editable list of items, each item of which is editable (kind of like an editable grid, in a way). I am using KnockoutJS. I cannot use just a simpl

相关标签:
3条回答
  • 2020-12-09 08:33

    To follow up on Tuan's answer, I needed to populate my objects based on data returned from a server method from an ASP.Net MVC controller, where the list of Products is contained in the view's Model, and the list of categories for the drop down box is in the ViewBag. I used the following code (see also http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html):

    var initialData = @Html.Raw( new JavaScriptSerializer().Serialize(Model));
    var categoryList = @Html.Raw( new JavaScriptSerializer().Serialize(ViewBag.CategoryList));
    
    var ObservableProduct = function(name, description, categoryId) {         
        this.Name = ko.observable(name);         
        this.Description = ko.observable(description);
        this.CategoryId = ko.observable(categoryId);
    };  
    
    var viewModel = {
        products: ko.observableArray(ko.utils.arrayMap(initialData, function(product) { 
                return new ObservableProduct(product.Name, product.Description, product.CategoryId); 
            })),
        categories: ko.observableArray(categoryList)       
    };
    
    $(function() {
        ko.applyBindings(viewModel);
    
    });
    

    Thanks, Tuan!

    0 讨论(0)
  • 2020-12-09 08:43

    I am using writable computed observables that are initialized in the call to ko.utils.arrayMap

    May be an overkill in your case, but it might help somebody else. See this jsFiddle sample

      // Writeable computed observables
      function Customer(id, firstName, lastName, preferred) {
         var self = this;
         self.id = id;
         self.firstName = firstName;
         self.lastName = lastName;
         // Non-Writeable computed observable
         self.fullName = ko.computed(function() {
            var fn = self.firstName;
            var ln = self.lastName;
            return ln ?  fn + ' ' + ln : fn;
         }, self);
         self.preferred = ko.observable(preferred);
         // Writeable computed observable
         self.isPreferred = ko.computed({
            read: function() {
               var preferredStr = self.preferred() || '';
               var isPreferredComputed = preferredStr.toUpperCase();
               return (isPreferredComputed === 'Y') ?  true : false;
            },
            write: function(value) {
               self.preferred( (!value) ? '' : (value ? 'Y' : ''));            
            },
            owner: self        
        });    
     }
      var mappedData = ko.utils.arrayMap(dataFromServer, function(customer) {
          return new Customer(customer.id, customer.firstName, customer.lastName, customer.preferred);
      });
    
    0 讨论(0)
  • 2020-12-09 08:50

    ko.utils.arrayMap doesn't map your viewmodel's properties as observables, and that's why you don't see them updated dynamically.

    If you define your CategoryId as an observable, you'll see it update as expected:

    var initialData = [
        {
            Name: "Television",
            CategoryId: ko.observable("1")
        },
        {
            Name: "Melon",
            CategoryId: ko.observable("2")
        }
    ];
    

    See this updated jsfiddle: http://jsfiddle.net/tuando/E7xPM/5/

    0 讨论(0)
提交回复
热议问题