The Goal
Read the data-product-id
from DOM
added by KnockoutJS.
The problem
I have the following markup:
<!-- ko foreach: Summary.products --> <li data-bind="attr: { 'data-product-id': id }"> <div class="product-summary-actions float-right"> <button class="btn btn-danger btn-mini remove-item"> <i class="icon-remove"></i> </button> </div> <div class="product-summary-quantity"> <h6 data-bind="text: infoComposition"></h6> </div> <div class="product-summary-description"> <p data-bind="text: name"></p> </div> </li> <!-- /ko -->
As you can see, there is a data-bind at the first line after the comment with attr
binding. Look:
<li data-bind="attr: { 'data-product-id': id }">
When I check my DOM using Chrome's console, I have the following:
<li data-bind="attr: { 'data-product-id': id }" data-product-id="1">...</li>
As you could see, data-product-id
was successfully applied. But, when I have to make an interation with him, no success.
There is a function in my application that is responsible to check if an item exists on my Products Summary, and the following loop does this:
$(element).each(function () { var $productId = $(this).closest("li").data("product-id"), $match = $(".summary") .find("li[data-product-id=" + $productId + "]").length > 0; console.log($match); });
Always the return is false. In other words, seems that jQuery doesn't consider the data-product-id
generated by KnockoutJS because if I manually add the data-product-id
attribute to my items (like the following markup), all works fine.
<!-- ko foreach: Summary.products --> <li data-product-id="1"> <div class="product-summary-actions float-right"> <button class="btn btn-danger btn-mini remove-item"> <i class="icon-remove"></i> </button> </div> <div class="product-summary-quantity"> <h6 data-bind="text: infoComposition"></h6> </div> <div class="product-summary-description"> <p data-bind="text: name"></p> </div> </li> <!-- /ko -->
Okay... Code
My necessary HTML:
<button class="btn btn-success btn-small add" title="Add to comparison list"> <i data-bind="attr: { class: ProductLayout.existsAtSummary($element) ? 'icon-minus' : 'icon-plus' }"> </i> </button>
My JS:
function ProductLayoutViewModel() { var self = this; self.itemQuantity = ko.observable(""); self.itemQuantityValid = ko.computed(function () { var q = self.itemQuantity(); return q != "0" && q != "00" && q != null && q != ""; }, this); self.existsAtSummary = function (element) { $(element).each(function () { $productId = $(this).closest("li").data("product-id"); $match = $(".summary") .find("li[data-product-id=" + $productId + "]").length; if (!$match) return true; else return false; }); }); }; ViewModel = { Summary: new SummaryViewModel(), ProductLayout: new ProductLayoutViewModel() }; $.ajax({ url: "/ProductsSummary/List?output=json", dataType: "json", success: function (data) { var mappingOptions = { create: function (options) { return (new (function () { this.finalMeasure = ko.computed(function () { return this.quantity() > 1 ? this.measure() + "s" : this.measure(); }, this); this.infoComposition = ko.computed(function () { return this.quantity() + ' ' + this.finalMeasure(); }, this); ko.mapping.fromJS(options.data, {}, this); })()); } }; ViewModel.Summary.products = ko.mapping.fromJS(data, mappingOptions); ko.applyBindings(ViewModel); } });
Someone knows how can I solve this problem? Thanks!