Reputation: 741
I am trying to write a reusable component library, and have come up with this issue which is bugging me for a time now.
I have overriden the template engine using the example that is provided. I think my problem is mentioned in his 'A quick note about rewriting templates' paragraph (I am not sure though, my problem might be different). But I don't have any idea how to implement it. Any help is appreciated. Here's the problem:
My template engine basically registers templates given as 'templateName' and 'markUp'. Firstly, I have a product model, which goes as:
var Product = function(img, brand, description){
this.img = img;
this.brand = brand;
this.description = description;
};
Then, I have my parent view as:
{
name: 'productlist-view',
template: '<productlist-view class="product-list">\
<ul data-bind="foreach: {data: productlist, as: \'product\'}">\
<product-box params="parent: $parent, productInfo: product" data-bind="click: getProduct"></product-box>\
</ul>\
</productlist-view>'
}
Now in the viewModel of this productlist-view
view, productlist
property is defined as an array of Product
instances. The product-box
component is supposed to create a viewModel and an associated template for each of these Product
s. The product-box component is registered to knockout using:
ko.components.register('product-box', {
'viewModel': function(params){
this.product = params.product;
this.getProduct = function(){
//Will perform an ajax call here
};
},
'template': '<div class="product-box" data-bind="click: getProduct">\
<img class="product-img fl" data-bind="attr: {src: product.img}"/>\
<p data-bind="text: product.brand"></p>\
<p data-bind="text: product.description"></p>\
</div>'
})
I know, in the code above there are two bindings for the getProduct
method. I will come to that. For now, just imagine the one in the productlist-view was not there.
The code above generates an html that goes like:
<productlist-view ....
<ul ....
<product-box ....
<div class="product-box" ....
<img .../>
<p ... />
<p ... />
</div>
</product-box>
<product-box ..... goes on
</ul>
</productlist-view>
In the above-code, the wrapper div
in the product-box
element is totally unnecessary since it just wraps the element. Moreover, the element is already wrapped within product-box
element. So I want to remove the wrapper div. The problem here is that, I need the whole product visual to be clickable, but I cannot bind the click event to the getProduct method from the productlist-view template. When the foreach
loop iterates in productlist-view
template, the $data points to model of the product, not the viewModel
(aka product-box).
How can I set this getProduct method, from the parent view?
Is there anyway to remove that unnecessary wrapper div in product-box?
In other words how can I have a clickable product-box component which goes like:
<productlist-view ....
<ul ....
<product-box data-bind="click: getProduct"....
<img .../>
<p ... />
<p ... />
</product-box>
...
</ul>
</productlist-view>
Upvotes: 3
Views: 1721
Reputation: 43881
You can make a custom binding handler that would attach a click binding to the parent, but that strikes me as too clever by half (and violates encapsulation). If your click
binding is associated with your component, it makes sense that the div
be part of the component.
Instead of using custom product-box tags, you can use a virtual tag and the component
binding, so you don't have an extraneous wrapper.
Upvotes: 1