【问题标题】:How can I nest a loop from a single array in knockoutjs?如何在 knockoutjs 中从单个数组嵌套循环?
【发布时间】:2018-12-23 17:21:09
【问题描述】:

为了简单起见,我有一个简单的数组。我要做的是循环遍历数组的第一类问题,然后循环遍历数组的第二类问题,依此类推。

“答案”将是文本输入字段或单选按钮或其他任何内容。

如何将两个循环“嵌套”在 knockout.js 中?我不能把它分成两个数组,因为那样我就失去了两个循环之间的关系。

//knockout.js viewModel
function SurveyViewModel() {
    var self = this;
    self.EvaluationElement = ko.observableArray([
        {category: "Category1", question: "Question #1"},
        {category: "Category1", question: "Question #2"},
        {category: "Category2", question: "Question #3"},
        {category: "Category2", question: "Question #4"},
        {category: "Category3", question: "Question #5"},
        {category: "Category3", question: "Question #6"},
        {category: "Category4", question: "Question #7"},

我想构建一个视图 (HTML),它本质上是一个嵌套如下的表格:

<table>
  <tr>
    <th colspan="3">Category 1</th>
  </tr>
  <tr>
    <td>Question #1</td>
    <td>Answer</td>
    <td></td>
  </tr>
  <tr>
    <td>Question #2</td>
    <td>Answer</td>
    <td></td>
  </tr>
  <tr>
    <td colspan="3">Category 2</td>
  </tr>
  <tr>
    <td>Question #3</td>
    <td>Answer</td>
    <td></td>
  </tr>
  <tr>
    <td>Question #4</td>
    <td>Answer</td>
    <td></td>
  </tr>
  <tr>
    <td>Question #5</td>
    <td>Answer</td>
    <td></td>
  </tr>
</table>

我正在尝试做这样的事情......有明显的错误,但希望它传达了我的想法。

<br>
<table class="table table-hover">
   <tbody data-bind="foreach: EvaluationElement/Category">
      <tr>
        <td colspan="2" data-bind="text: category></td>
      </tr>
      <data-bind="foreach: EvaluationElement">
           <tr>
            <td data-bind="text: question"></td>
            <td>Answer</td>
            <td></td>
          </tr>
       <// close loop>
   </tbody>
</table>
<br>
<button data-bind="click: submitSurvey">Submit</button>

【问题讨论】:

    标签: javascript arrays knockout.js


    【解决方案1】:

    您应该在视图模型中重构数据,以保持视图美观和简单。如果您的视图需要每个类别的表格主体,这就是视图模型数据应该反映的内容。

    要将问题列表重组为类别列表,您可以使用 Knockout 的pureComputed

    我们创建一个函数,将数据从[ { category, question } ] 转换为[ { category, questions: [ { category, question ] } ]

    这非常类似于groupBy。编写分组函数的方法有很多种;如果您想了解有关不同方法的更多信息,请搜索“在 javascript 中按属性分组”。

    使用新结构,视图非常类似于您想要的格式:

    function SurveyViewModel() {
      var self = this;
      self.EvaluationElement = ko.observableArray([{
          category: "Category1",
          question: "Question #1"
        },
        {
          category: "Category1",
          question: "Question #2"
        },
        {
          category: "Category2",
          question: "Question #3"
        },
        {
          category: "Category2",
          question: "Question #4"
        },
        {
          category: "Category3",
          question: "Question #5"
        },
        {
          category: "Category3",
          question: "Question #6"
        },
        {
          category: "Category4",
          question: "Question #7"
        }
      ]);
    
      self.categories = ko.pureComputed(function() {
        // Assumes questions sorted by category
        return self.EvaluationElement().reduce(
          function(cats, q, i, qs) {
            const prev = qs[i - 1];
            
            if (!prev || prev.category !== q.category) {
              cats.push({ 
                category: q.category,
                questions: [ q ]
              });
            } else {
              cats[cats.length - 1].questions.push(q);
            };
            
            return cats;
          }, []);
      });
    };
    
    ko.applyBindings(new SurveyViewModel());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <table>
      <tbody data-bind="foreach: categories">
        <tr>
          <td colspan="2" data-bind="text: category"></td>
        </tr>
        <!-- ko foreach: questions -->
        <tr>
          <td data-bind="text: question"></td>
          <td>Answer</td>
          <td></td>
        </tr>
        <!-- /ko -->
      </tbody>
    </table>

    【讨论】:

    • 谢谢,很有帮助。
    猜你喜欢
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多