【问题标题】:Knockout.js: disable other checkboxes when one checkbox is selectedKnockout.js:当一个复选框被选中时禁用其他复选框
【发布时间】:2018-08-05 20:36:32
【问题描述】:

我是 Knockout 的新手,我正在努力解决以下问题。

我制作了一些可点击的产品 div(带有隐藏的复选框)。如果有人点击一个 div,一个隐藏的复选框会被选中并且样式会改变。

现在我想添加依赖项,因为有些产品不能同时订购。我想根据复选框值(真/假)来执行此操作。因此,假设选择了产品 1,则应使用附加类“disabledDiv”禁用产品 2 和 3。但是,此事件更改活页夹对我没有用。我什至没有发出警报。

self.valueCheckboxChanged = function() {
  alert('value has changed')
}

谁能帮帮我,我很茫然。我做了一个简化的 JSFiddle (https://jsfiddle.net/Seabiscuito/f1qnr8a2/) 来说明问题。

【问题讨论】:

    标签: jquery checkbox knockout.js knockout-3.0


    【解决方案1】:

    修复 1: 从复选框中删除 value 绑定。

    修复 2:hidden 属性添加到复选框以防止出现任何事件冒泡问题(点击输入会切换值,冒泡到 div 并将其切换回)

    修复 3: 订阅复选框的 isChecked observable,而不是使用 change 事件。例如:

    self.checkedProducts = ko.pureComputed(function() {
      return this.products().filter(function(p) {
        return p.isChecked();
      });
    }, this);
    
    self.checkedProducts.subscribe(function(checked) {
      // Do something with the checked products
    }, this);
    

    最后一部分是最复杂的部分。确保您不会陷入无限循环! 如果你解释了你想要创建什么样的依赖,我可以编辑最后一部分以更好地反映你的需求。

    这是一个通过subscribe 显示项目之间关系的示例:

    function Cart(products) {
      this.products = products.map(Product.fromData);
      
      const main = this.products[0];
      const others = this.products.slice(1);
        
      main.isChecked.subscribe((included) => {
        const action = included 
          ? Product.disable
          : Product.enable;
          
        others.forEach(action);
      });
    };
    
    function Product(name) {
      this.name = name;
      this.isChecked = ko.observable(false);
      this.enabled = ko.observable(true);
    };
    
    Product.prototype.toggle = function() {
      if (!this.enabled()) return;
      this.isChecked(!this.isChecked());
    };
    
    Product.prototype.enable = function() {
      this.enabled(true);
    };
    
    Product.prototype.disable = function() {
      this.enabled(false);
      this.isChecked(false);
    };
    
    Product.enable = p => p.enable();
    Product.disable = p => p.disable();
    Product.fromData = name => new Product(name);
    
    
    ko.applyBindings(new Cart(["Deluxe Lunch", "Drink", "Food"]));
    li { opacity: .5; list-style: none; padding: 1em; border-radius: 3px; border: 1px solid black; margin-bottom: .25em; }
    .isChecked { background: yellow }
    .isEnabled { opacity: 1; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    
    <ul data-bind="foreach: products">
    
      <li data-bind="click: toggle.bind($data), css: { isChecked: isChecked, isEnabled: enabled }">
        <input type="checkbox" data-bind="checked: isChecked" hidden />
        <span data-bind="text: name"></span>
      </li>
    
    
    </ul>

    【讨论】:

    • 如果有人选择了产品 1,他们就不能再选择产品 2 和 3。因此,如果有人选择了产品 1,我想禁用产品 2 和 3 的整个 div,这样那些 div 不再可点击,客户无法选择这些产品。我之前通过向 extraProduct div 添加另一个类('disabledDiv')来做到这一点。
    • 我已经用产品 4 更新了我的 JSFiddle,以说明我试图用产品 2 和 3 完成的工作:jsfiddle.net/Seabiscuito/f1qnr8a2/37 产品 4 现在已经被禁用,但我希望它添加类(' disabledDiv') 选择产品 1 时。希望现在更清楚了!
    • 我添加了一个快速示例,展示了如何链接不同项目的状态。不过,我很难看出你会在哪里定义有关产品之间依赖关系的逻辑。
    • 感谢您的帮助!我正在为最后一件事而苦苦挣扎。我的数组由具有各种产品变量(名称、价格、持续时间等)的对象组成。我无法将代码从一个简单的数组切换到一个更复杂的包含对象的数组。一旦我切换到一个包含对象的数组,[Object Object] 中的名称就会更改对于图像:ibb.co/dWMEVx
    • 我做了一个 JSFiddle 的更新版本:jsfiddle.net/Seabiscuito/f1qnr8a2 最后,价格也应该是 data-bind="text: price",但我无法做到这一点..跨度>
    猜你喜欢
    • 1970-01-01
    • 2013-06-29
    • 2011-05-24
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 2013-10-11
    相关资源
    最近更新 更多