【问题标题】:How to display data with multiple arrays as an html table with angular.js?如何使用 angular.js 将具有多个数组的数据显示为 html 表?
【发布时间】:2014-02-11 09:38:49
【问题描述】:

假设数据结构如下:

[
 {name: 'first', data1: [1,2,3], data2: [4,5]},
 {name: 'second', data1: [9,8,7], data2: [6,6,4,5]}, 
 ...
]

(注意data1和data2不是固定长度,也不一定是相同的长度)。

我想创建一个像这样的 html 表格:

<table>
 <thead>
   <th> Name </th>
   <th> Data 1 </th>
   <th> Data 2 </th>
 </thead>
 <tbody>
  <tr>
    <td rowspan="4">first</td>
    <td>1</td>
    <td>4</td>
  </tr>
  <tr>   
    <td>2</td>
    <td>5</td>
  </tr>
  <tr>   
    <td>3</td>
    <td>&nbsp;</td>
  </tr>
  <tr>   
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>

  <tr>
    <td rowspan="5">first</td>
    <td>9</td>
    <td>6</td>
  </tr>
  <tr>   
    <td>8</td>
    <td>6</td>
  </tr>
  <tr>   
    <td>7</td>
    <td>5</td>
  </tr>
  <tr>   
    <td>&nbsp;</td>
    <td>5</td>
  </tr>
  <tr>   
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
 </tbody>
<table>

请注意,在显示中,在每一列的最后一位数据之后至少有一个额外的空单元格。我希望该单元格(data1 和 data2 的第一个空单元格)有一个 ng-click 处理程序,如果单击该处理程序,它将在该列中显示输入而不是 %nbsp;可以输入一个新值。

最好的方法是什么?

目前,我几乎可以通过在观察第一个变量的范围内设置第二个变量来创建上述结构,当第一个变量发生变化时,它会展平数据,因此上述数据将存储在另一个变量中:

[ { name: 'first', rowsNeeded: '4', data: [ [1,4], [2,5], [3, undefined], [undefined, undefined]], ... ]

然后像这样渲染它

 <tbody ng-repeat="item in flattenedData">
    <tr ng-repeat="data in item.data">
        <td ng-if="$first" rowspan="{{data.rowsNeeded}}">{{data.name}}</td>
        <td>{{data[0] == undefined ? '&nbsp;' : macroData[0] }}</td>
        <td>{{data[1] == undefined ? '&nbsp;' : macroData[1] }}</td>
    </tr>
</tbody>

但我想知道一些事情。一,我真的需要使用监视语句来创建表的第二个变量还是有更清洁的方法?第二,我不确定如何添加点击事件,所以在每列的第一个“未定义”中,我可以添加一个而不是“&nbsp”。最后,真的有必要为每一行设置不同的 tbody 标签吗?

感谢您的帮助!!

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    总体思路是将数据格式提取到过滤器中。从那里开始,我会将所有内容组合成指令以简化表格组件的使用。此示例 (JSBin) 仅显示过滤器和模板,不是最佳的,但可以正常工作:

    <table>
        <thead>
            <tr>
                <th>Name</th>
                <th ng-repeat="key in datas[0]|dataKeys">
                    Data {{$index+1}}
                </th>
            </tr>
        </thead>
        <tbody ng-repeat="set in datas">
            <tr ng-repeat="row in (set|setMaxLength|range)">
                <td
                  rowspan="{{(set|setMaxLength)+1}}"
                  ng-if="!$index"
                >
                    {{set.name}}
                </td>
                <td ng-repeat="data in (set|setDatas)">
                    {{data[$parent.$index]}}
                </td>
            </tr>
            <tr>
                <td
                  ng-repeat="data in (set|setDatas)"
                  ng-click="editing = true"
                >
                    <span ng-if="!editing">&nbsp;</span>
                    <form
                      ng-submit="data[data.length] = input.value"
                      name="input"
                    >
                        <input
                          type="text"
                          ng-if="editing"
                          ng-model="input.value"
                          autofocus
                        >
                    </form>
                </td>
            </tr>
        </tbody>
    </table>
    
    angular
    .module("app", [])
    .controller("ctrl", function($scope) {
        $scope.datas = [{
            name: 'first',
            data1: [1, 2, 3],
            data2: [4, 5]
        }, {
            name: 'second',
            data1: [9, 8, 7],
            data2: [6, 6, 4, 5]
        }];
    })
    .filter("range", function() {
        return function(length) {
            return Array.apply(0, Array(length))
            .map(function(_, i) {
                return i;
            })
        }
    })
    .filter("dataKeys", function() {
        return function(set) {
            return Object.keys(set)
            .filter(function(key) {
                return key.indexOf("data") !== -1;
            })
        }
    })
    .filter("setDatas", function($filter) {
        return function(set) {
            return $filter("dataKeys")(set)
            .map(function(key) {
                return set[key]
            });
        }
    })
    .filter("setMaxLength", function($filter) {
        return function(set) {
            return $filter("dataKeys")(set)
            .map(function(key) {
                return set[key].length;
            })
            .sort().pop();
        }
    })
    

    【讨论】:

    • 这是使用过滤器的好方法!非常感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 2014-06-22
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    相关资源
    最近更新 更多