knockout click binding - 阻止绑定除clicked元素之外的所有元素

时间:2017-08-13 15:40:38

标签: javascript jquery knockout.js

我对淘汰赛中的点击装订有疑问。我差点找到解决办法,但仍然不是我想要的。我使用模板两个列表(模板是相同的)。在列表中我有几个具有相同绑定的元素,在开始时我可以单击任何按钮,但是当我单击某个元素时,我想阻止从一个列表中选择/单击其他项目的能力。示例将更好地解释: JS

function AppViewModel() {
    var self = this;
    self.people = ko.observableArray([
        { name: 'Bert', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' },
        { name: 'Charles', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' },
        { name: 'Denise', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' }
    ]);
    self.workers = ko.observableArray([
        { name: 'Bart', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' },
        { name: 'Joey', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' },
        { name: 'Daniel', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' }
    ]);
    self.checkVoice = function() {
      console.log('test');
    };
}

ko.applyBindings(new AppViewModel());

HTML

<h2>List one</h2>
<div data-bind="template: { name: 'person', data: people }"></div>
<h2>List two</h2>
<div data-bind="template: { name: 'person', data: workers }"></div>

<script type="text/html" id="person">
    <!-- ko foreach: $data -->
    <div data-bind="text: $data.name"></div>
    <button data-bind="click: $root.checkVoice">like</button>
    <button data-bind="click: $root.checkVoice">dislike</button>
    <!-- /ko --> 
</script>

link to fiddle

我的高尔夫是:当我点击“Bert”名称的按钮时,我想关闭这个列表中点击休息按钮的可能性,但我希望有可能在第二个列表上完全相同。 这可以只使用一个模板吗? 现在我有这样的事情:

data-bind="click: function(data, event, type) { if(buttonClickedObservable()) { $root.checkAvailability($data, event, 'standard'); } }"

这个解决方案还不错,但是不仅可以在一个

上点击这两个列表

2 个答案:

答案 0 :(得分:1)

我在理解您的要求时遇到了一些困难。但也许组件而不是模板可能更适合您的需求。使用组件,您将获得模板和视图模型。

这是一个小提琴https://jsfiddle.net/odygrxt8/4/

我再也不太了解你关于禁用按钮的要求,但是如果你运行小提琴只有一个喜欢或不喜欢在任何给定的列表中活动。

这里是您可能需要更改逻辑以满足您的实际要求的组件,但希望它会给您一个想法。

ko.components.register('like-widget', {
  viewModel: function(params) {
    var self = this;
    this.data = params.value;
    this.selectedName = ko.observable('');
    this.choice = ko.observable('');
    this.likeIt = function(row) {
      self.selectedName(row.name);
      self.choice('like');
    };
    this.dislikeIt = function(row) {
      self.selectedName(row.name);
      self.choice('dislike');
    };
  },
  template: ' <div data-bind="foreach: data">\
           <div data-bind="text: $data.name"></div>\
            <button data-bind="click: $parent.likeIt, css: {\'btn-danger\': ($data.name == $parent.selectedName() && $parent.choice() == \'like\')}" class="btn">like</button>\
             <button data-bind="click: $parent.dislikeIt, css: {\'btn-warning\': ($data.name == $parent.selectedName() && $parent.choice() == \'dislike\')}" class="btn">Dislike</button>\
         </div>'
});

答案 1 :(得分:1)

以下是使用自定义绑定完成此操作的一个选项:

ko.bindingHandlers.groupClick = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    var accessor = valueAccessor();
    var groupKey = allBindings().groupKey;    
    groupKey._groupClicked = groupKey._groupClicked || ko.observable(false);

    $(element).click(function(){
        groupKey._groupClicked(true);
    });

    var canClick = ko.computed(function(){
        return !groupKey._groupClicked();
    });
    var fontColor = ko.computed(function(){
        return { color: canClick() ? 'black' : 'silver' };
    });
    ko.applyBindingsToNode(element, { enable: canClick, style: fontColor });
  }
}

绑定使用“组”来跟踪哪些按钮共享相同的状态,在这种情况下,该组是父数组。然后,绑定将一个observable附加到父数组以存储状态,并将同一组数组中的所有元素绑定到该observable。

function AppViewModel() {
    var self = this;
    self.people = ko.observableArray([
        { name: 'Bert', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' },
        { name: 'Charles', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' },
        { name: 'Denise', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' }
    ]);
    self.workers = ko.observableArray([
        { name: 'Bart', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' },
        { name: 'Joey', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' },
        { name: 'Daniel', bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' }
    ]);
    self.checkVoice = function() {
      console.log('test');
    };
}

ko.bindingHandlers.groupClick = {
	init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
  	var accessor = valueAccessor();
    var groupKey = allBindings().groupKey;    
    groupKey._groupClicked = groupKey._groupClicked || ko.observable(false);
    
    $(element).click(function(){
    	groupKey._groupClicked(true);
    });
    
    var canClick = ko.computed(function(){
    	return !groupKey._groupClicked();
    });
    var fontColor = ko.computed(function(){
    	return { color: canClick() ? 'black' : 'silver' };
    });
    ko.applyBindingsToNode(element, { enable: canClick, style: fontColor });
  }
}
 
ko.applyBindings(new AppViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h2>List one</h2>
<div data-bind="template: { name: 'person', data: people }"></div>
<h2>List two</h2>
<div data-bind="template: { name: 'person', data: workers }"></div>

<script type="text/html" id="person">
    <!-- ko foreach: $data -->
    <div data-bind="text: $data.name"></div>
    <button data-bind="groupClick: $root.checkVoice, groupKey: $parent">like</button>
    <button data-bind="groupClick: $root.checkVoice, groupKey: $parent">dislike</button>
    <!-- /ko --> 
</script>

<script type="text/html" id="person">
    <!-- ko foreach: $data -->
    <div data-bind="text: $data.name"></div>
    <button data-bind="groupClick: $root.checkVoice, groupKey: $parent">like</button>
    <button data-bind="groupClick: $root.checkVoice, groupKey: $parent">dislike</button>
    <!-- /ko --> 
</script>