简体   繁体   中英

knockoutjs custom elements(components) , viewmodel properties undefined

im stuck a bit with knockoutjs.
Here is a fiddle for the problem.
I've added some simplified logic there.
Shortly, i have a product list, i should populate it from server, and on click on the product item i need the product data(with the observables), so i can update the other view models.
Note that not all properties are observables (names of products etc, wont change). Each product item is a ko component with viewmodel.

Why on button click, the properties of the non-observables , are undefined ? And also, check the productTemplate , im accessing some properties via product , and the observables via $data (they dont work otherwise - why?). Thanks.

Here is sample html markup

<div class="products_wrapper">
    <section class="products">
        <ul data-bind="foreach: { data: products, as: 'product' }">
            <li>
                <product-item params="product: product"></product-item>
            </li>
        </ul>
    </section>
</div>

Here is the component code:

<script type="text/html" id='productTemplate'>
<button type="button" name="product" data-bind="attr: { id: product.ProductId }">
    <span data-bind='text: product.Name'></span>
    <span class="product-item-quantity" data-bind='text: $data.Quantity'></span>
</button></script> 

and here are view models and component registration:

var some = some || {};
some.viewmodel = some.viewmodel || {};
some.viewmodel.product = function (item) {
  var self = this;
  //parameters
  self.ProductId = item.ProductId;
  self.Name = item.Name;
  self.Quantity = ko.observable(0);

  self.increaseQty = function increaseQty() {
    self.Quantity(self.Quantity() + 1);
  };
};

some.viewmodel.products = function () {
  var self = this;

  self.products = ko.observableArray();
  self.populate = function (data) {
    self.products(data);
  };
  self.getData = function () {
    self.populate(the json data here);
  };
};
ko.components.register('product-item', {
  viewModel: some.viewmodel.product,
  template: {
    element: 'productTemplate'
  }
});

Init here:

var products = new some.viewmodel.products();
ko.applyBindings(products, $('.products_wrapper')[0]);
products.getData();

$(".products").on('click', 'button', function () {
  var productcontext = ko.contextFor(this);
  var product = ko.dataFor(this);
  product.increaseQty();
  //$('.debug').append();//debug here
});

In your case you need to insert product property like this:

  self.ProductId = item.product.ProductId;
  self.Name = item.product.Name;

Click a button at: JS Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM