Set viewModel = $data for Component

╄→尐↘猪︶ㄣ 提交于 2019-12-25 00:36:53

问题


I'm just starting to get my head around Knockout Components. Right now I'm trying to create a "Template Only" Component. The issue I ran into is getting the viewmodel of the component set to the $data of where I'm using the Component. I've modified the example from the Knockout page (http://knockoutjs.com/documentation/component-overview.html)

Here's a plunk that shows what I've done: http://plnkr.co/edit/23PVEW9aQ63A9yq2wRJp

I'm using the component in a 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 the component:

ko.components.register('like-widget', {
  viewModel: function(params) {
    // Data: value is 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">\
            You <strong data-bind="text: userRating"></strong> it\
        </div></div>'
});

Doing it this way works, but it seems like there would be an easier way to set the viewModel of component to $data.

Is this the correct way or am I missing something?


回答1:


Although you can pass in the $data as a parameter, please note that you have now tightly coupled the design of the component to the design of the view model. A more reusable approach would be to pass the name and userRating in as parameters, and use those to construct a view model for the component that knows nothing about the structure of the product view model.

That being said, you don't need to pass $data in as a parameter to the component in order to have access to it. Instead, you can use ko.contextFor on the element the component is bound to, and get at the $data that 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




回答2:


You could define the like and dislike functions in the Product class and use the template binding, so you can just bind the whole Product object to the template.

I've forked your plunk to show how I did it

http://plnkr.co/edit/fYaBw1Yjsivg6O8x3JgB

<div data-bind="template: { name: 'like-template', data: $data}"></div>

And the template would look like this

<script type="text/html" id="like-template">
        <div class="like-or-dislike" data-bind="visible: !userRating()">
            <button data-bind="click:like">Like it</button>
            <button data-bind="click:dislike">Dislike it</button>
        </div>
        <div class="result" data-bind="visible: userRating">
            You <strong data-bind="text: userRating"></strong> it
        </div></div>
  </script>


来源:https://stackoverflow.com/questions/29546961/set-viewmodel-data-for-component

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!