knockout.js - Set viewModel = $data for Component -
i'm starting head around knockout components. right i'm trying create "template only" component. issue ran getting viewmodel of component set $data of i'm using component. i've modified example knockout page (http://knockoutjs.com/documentation/component-overview.html)
here's plunk shows i've done: http://plnkr.co/edit/23pvew9aq63a9yq2wrjp
i'm using component in foreach like:
<ul data-bind="foreach: products"> <li class="product"> <strong data-bind="text: name"></strong> <div data-bind="component: { name: 'like-widget', params: {data: $data}}"></div> </li> </ul>
here's component:
ko.components.register('like-widget', { viewmodel: function(params) { // data: value either null, 'like', or 'dislike' this.data = params.data; // behaviors this.like = function() { this.data.userrating('like'); }.bind(this); this.dislike = function() { this.data.userrating('dislike'); }.bind(this); }, template: '<div data-bind="with: data"><div class="like-or-dislike" data-bind="visible: !userrating()">\ <button data-bind="click: $parent.like">like it</button>\ <button data-bind="click: $parent.dislike">dislike it</button>\ </div>\ <div class="result" data-bind="visible: userrating">\ <strong data-bind="text: userrating"></strong> it\ </div></div>' });
doing way works, seems there easier way set viewmodel of component $data.
is correct way or missing something?
although can pass in $data parameter, please note have tightly coupled design of component design of view model. more reusable approach pass name , userrating in parameters, , use construct view model component knows nothing structure of product view model.
that being said, don't need pass $data in parameter component in order have access it. instead, can use ko.contextfor on element component bound to, , @ $data way.
example:
ko.components.register('like-widget', { viewmodel: { createviewmodel: function (params, componentinfo) { var context = ko.contextfor(componentinfo.element); var self = context.$data; return ko.utils.extend(context.$data, { ratingbuttonvisible: ko.computed(function() { return (self.userrating()==null); }), ratingdescriptionvisible: ko.computed(function() { return !(self.userrating()==null); }), like: function() { self.userrating('like'); }, dislike: function() { self.userrating('dislike'); } }); } }, template: { element: 'like-template' } }); ko.applybindings(new myviewmodel());
working jsfiddle