【问题标题】:Show/Hide div within a single row in a foreach loop - KnockoutJS在 foreach 循环的单行中显示/隐藏 div - KnockoutJS
【发布时间】:2021-07-17 13:19:28
【问题描述】:

我尝试了几种方法,但都没有成功。希望得到一些建议!

目标:我有一个表格,其中每一行都是一个订单,但是在该行中,如果需要进行更改,则会在下方显示一个 div(红色)。当单击/切换该行上的按钮时,这需要显示/隐藏(按钮为:进行更改)

问题:除了进行更改切换之外,我的所有按钮都在工作。尝试了可见的 observable,但我能得到的最接近的是切换整个表的 div 可见性,而不是每行。

//Class to represent a row in the table
         function orderDetail(order, orderChange) {
             var self = this;
             self.order = ko.observable(order);
         self.orderChange = ko.observable(orderChange);
         }
         
         //Overall viewmodel, plus initial state
         function FoodViewModel() {
             var self = this;
         
             self.foodTypes = [
                { foodType: "Please Select"},
            { foodType: "Veg"},
            { foodType: "Meat"}
             ];    
         
             self.orders = ko.observableArray([
                 new orderDetail(self.foodTypes[0], self.foodTypes[0])
             ]);
         
             // Add and remove rows
             self.addOrder = function() {
                 self.orders.push(new orderDetail(self.foodTypes[0], self.foodTypes[0]));
             }
             self.removeOrder = function(order) { self.orders.remove(order) }
        
         
         }

         ko.applyBindings(new FoodViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table>
         <thead>
            <tr>
               <th>Orders</th>
               <th></th>
           <th></th>
            </tr>
         </thead>
         <tbody data-bind="foreach: orders">
            <tr>
               <td>
        <div><select data-bind="options: $root.foodTypes, value: order, optionsText: 'foodType'" id="foodList"></select></div>
            <div><select data-bind="options: $root.foodTypes, optionsText: 'foodType', value: orderChange" id="foodListChange" style="color: red;"></select></div>
           </td>
               <td>
        <button class="button button2" >Make Changes</button>
           </td>
               <td>
        <button class="button button1" href="#" data-bind="click: $root.removeOrder">Remove</button>
           </td>
            </tr>
         </tbody>
      </table>
      <button data-bind="click: addOrder" class="button">Add Order</button>

提前致谢!

【问题讨论】:

    标签: javascript html foreach knockout.js visibility


    【解决方案1】:

    如果您希望用户界面对 Knockout 中的某些内容做出反应,请创建一个 observable。

    在这种情况下,您希望有条件地显示部分 UI(显然是为了切换编辑模式),所以让我们创建:

    • 可观察到的editModetruefalse,用于存储UI 状态
    • 一个函数toggleEditMode在两种状态之间切换,将其绑定到按钮
    • if: editModeifnot: editMode 绑定,以相应地显示 UI 的不同部分

    function OrderDetail(params) {
      var self = this;
      params = params || {};
      self.order = ko.observable(params.order);
      self.orderChange = ko.observable(params.orderChange);
      self.editMode = ko.observable(true);
      self.buttonCaption = ko.pureComputed(function () {
        return self.editMode() ? "Done" : "Edit";
      });
      self.toggleEditMode = function () {
        self.editMode(!self.editMode());
      }
    }
    
    function OrderList(params) {
      var self = this;
      params = params || {};
    
      self.foodTypes = ko.observableArray(params.foodTypes);
      self.orders = ko.observableArray();
    
      self.addOrder = function(foodType) {
        self.orders.push(new OrderDetail());
      }
      self.removeOrder = function(order) {
        self.orders.remove(order);
      }
    }
    
    var vm = new OrderList({
      foodTypes: [
        {foodType: "Veg"},
        {foodType: "Meat"}
      ]
    });
    ko.applyBindings(vm);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <table>
      <thead>
        <tr>
          <th style="width: 150px;">Orders</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody data-bind="foreach: orders">
        <tr>
          <td>
            <div data-bind="ifnot: editMode">
              <!-- ko with: order -->
              <span data-bind="text: foodType"></span>
              <!-- /ko -->
            </div>
            <div data-bind="if: editMode">
              <select data-bind="
                options: $root.foodTypes,
                value: order,
                optionsText: 'foodType',
                optionsCaption: 'Please select&hellip;'
               "></select>
            </div>
          </td>
          <td>
            <button class="button button2" data-bind="
              click: toggleEditMode,
              text: buttonCaption,
              enable: order
            "></button>
            <button class="button button1" href="#" data-bind="
              click: $root.removeOrder
            ">Remove</button>
          </td>
        </tr>
      </tbody>
    </table>
    <button data-bind="click: addOrder" class="button">Add Order</button>
    <hr>
    <pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

    注意事项

    • 不要将“请选择”作为食物类型的一部分。这就是 optionsCaption 绑定的用途。
    • 我已经参数化了视图模型(参见params 对象)。这比硬编码值或使用长参数列表更有效,特别是如果您想稍后使用映射插件。
    • 只要没有通过enable: order 绑定选择订单,“完成”按钮就会被禁用,即如果order 属性为空,enable 绑定将使按钮保持禁用状态。
    • with: order 绑定具有类似的目的。只有当实际有 order 值要显示时,它才会显示其内容。这将防止出现不完整的 OrderDetail 实例的渲染错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-02
      • 2012-03-09
      • 1970-01-01
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多