Angular ng-repeat with directive(在级联重复表中)

时间:2017-08-29 11:32:37

标签: javascript angularjs

我是Angular的新手。我做了一个"重复级联表": 每行都是连接的。如果在第1行第1列(R1C1)中发生了某些变化,则该行中的其他2列将进行级联。

我创造了两个"掠夺者"证明我的问题。

  1. 使用自定义指令(用于ng-repeat) (documentation
  2. 相同但没有指令(http://plnkr.co/edit/J8k74C3AUIAxv6rEKcWL?p=preview
  3. 示例2 中,当处于R1C1"功能"选择,并在R1C2中选择一个随机选项,然后使用级联选项填充R1C3。

    在同一个例子中,当添加一行(R2)并且在R2C1"部门"在R2C2中选择了另一个随机选项,R2C3填充了级联选项但是...... R1C3也改变了......

    当我使用自定义指令时,这个问题就解决了。但是,每行的删除按钮不起作用($ index ...也是如此),并且还没有填充json格式的表单数据。我怎样才能在这两个掠夺者之间做出完美匹配?我对此表示不满:(

    PLUNKER CODE(例2):

    JS:

    'use strict';
    /* global $ */
    
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope, $timeout, filterService) {
      $scope.filters = filterService.getFilters();
    
          $scope.addNewForm = function (){
            $scope.filters.push({});
          };
    
          $scope.attribute = filterService.getAttribute();
          $scope.comparison = function(index, field) {
            $scope.comparisonType = filterService.getComparison($scope.attribute[field]);
          };
          $scope.value = function(index, parent, field) {
            $scope.vType = filterService.getValueType($scope.attribute[parent], $scope.comparisonType[field]);
          }
    })
    
    app.service('filterService', function() {
    
      var attribute = [
        {name: 'Building year', type: 'integer', id: 1},
        {name: 'Square meters', type: 'integer', id: 2},
        {name: 'Function', type: 'select', id: 3},
        {name: 'Department', type: 'multiselect', id: 4},
        {name: 'Date of possesion', type: 'date', id: 5},
      ];
    
      this.getFilters = function() {
        return [];
      }
    
      this.getAttribute = function() {
        return attribute;
      }
    
      this.getComparison = function(attribute) {
        console.log(attribute.name)
         var comparisonType = [];
        if (attribute.type == 'select' || attribute.type == 'multiselect') {
          comparisonType = [
            {name: 'is', id: 1},
            {name: 'is not', id: 2},
            {name: 'one of', id: 3},
            {name: 'not one of', id: 4},
          ]
        } else if (attribute.type == 'integer' || attribute.type == 'date') {
          comparisonType = [
            {name: 'is', id: 1},
            {name: 'is not', id: 2},
            {name: 'greater then', id: 3},
            {name: 'smaller then', id: 4},
          ]
    
        }
        return comparisonType;
      }
    
      this.getValueType = function(attribute, comparison) {
        console.log(attribute.name)
        console.log(comparison.name)
        var vType = [];
        var vTypes = [
            {name: 'Department 1', id: 1, fk: 4},
            {name: 'Department 2', id: 2, fk: 4},
            {name: 'Department 3', id: 3, fk: 4},
            {name: 'Department 4', id: 4, fk: 4},
            {name: 'Department 5', id: 5, fk: 4},
            {name: 'Function 1', id: 6, fk: 3},
            {name: 'Function 2', id: 7, fk: 3},
            {name: 'Function 3', id: 8, fk: 3},
            {name: 'Function 4', id: 9, fk: 3},
            {name: 'Function 5', id: 10, fk: 3},
          ]
        var tmp = [];
    
        angular.forEach(vTypes, function(value, key) {
          if (value.fk === attribute.id)
            tmp.push(value);
        });
    
    
        if (attribute.type == 'select') {
          vType = [
            {name: 'Department 1', id: 1, fk: 4},
            {name: 'Department 2', id: 2, fk: 4},
            {name: 'Department 3', id: 3, fk: 4},
            {name: 'Department 4', id: 4, fk: 4},
            {name: 'Department 5', id: 5, fk: 4},
            {name: 'Function 1', id: 6, fk: 3},
            {name: 'Function 2', id: 7, fk: 3},
            {name: 'Function 3', id: 8, fk: 3},
            {name: 'Function 4', id: 9, fk: 3},
            {name: 'Function 5', id: 10, fk: 3},
          ];
        }
        //return vType;
        return tmp;
      }
    });
    

    HTML:

    <!DOCTYPE html>
    <html ng-app="myApp">
    
      <head>
        <!-- Twitter bootstrap -->
        <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
    
        <!-- apiCheck is used by formly to validate its api -->
        <script src="//npmcdn.com/api-check@latest/dist/api-check.js"></script>
        <!-- This is the latest version of angular (at the time this template was created) -->
        <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
    
        <!-- This is the latest version of formly core. -->
        <script src="//npmcdn.com/angular-formly@latest/dist/formly.js"></script>
        <!-- This is the latest version of formly bootstrap templates -->
        <script src="//npmcdn.com/angular-formly-templates-bootstrap@latest/dist/angular-formly-templates-bootstrap.js"></script>
    
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
        <script src="https://rawgithub.com/eligrey/FileSaver.js/master/FileSaver.js" type="text/javascript"></script>
        <script src="script.js"></script>
      </head>
    
      <body ng-controller="myCtrl">
    
          <table class="table table-bordered" cellspacing="0" width="100%">
    
            <th>Attribute</th>
            <th>Compare</th>
            <th>Value</th>
            <th></th>
    
            <tbody>
              <tr data-ng-repeat="item in filters" class="text-center">
                <td>
                  <select class="form-control" 
                  ng-options='k as v.name for (k,v) in attribute' 
                  ng-change='comparison($index, item.check1)' 
                  ng-model='item.check1'>
                    <option value='' disabled>Select...</option>
                  </select>
                </td>
                <td>
                  <select ng-if="item.check1" class="form-control" 
                  ng-model='item.check2' 
                  ng-options='a as b.name for (a,b) in comparisonType' 
                  ng-change='value($index, item.check1, item.check2)'>
                    <option value='' disabled>Select...</option>
                  </select>
                </td>
                <td>
    
                  <!--DATE-->
                  <input class="form-control" ng-if="item.check1==='4' && item.check2"
                  type="date" ng-model='item.check3'>
                  </input>
    
                  <!--INTEGER-->
                  <input ng-if="item.check1==='0' && item.check2" 
                  class="form-control" ng-model='item.check3' type="number" 
                  </input>
    
                  <!--SELECT-->
                  <select ng-if="item.check1==='2' && item.check2" 
                  class="form-control" ng-model='item.check3' 
                  ng-options='c as d.name for (c,d) in vType'>
                    <option value='' disabled>Select...</option>
                  </select>
    
                  <!--MULTIPLE-->
                  <select multiple ng-if="item.check1==='3'" 
                  class="form-control" ng-model='item.check3' 
                  ng-options='c as d.name for (c,d) in vType'>
                  </select>
    
                </td>
                <td>
                  <button data-index="$index" type="button" 
                  class="btn btn-sm btn-danger" 
                      ng-click="filters.splice($index, 1)" >
                    Remove
                  </button>
                </td>
              </tr>
            </tbody>
          </table>
    
          <button class="btn btn-default" id="addMore" aria-hidden="true" 
          ng-click="addNewForm()">Add</button>
          <pre>{{filters | json}}</pre>
    
    
      </body>
    
    </html>
    

2 个答案:

答案 0 :(得分:1)

在第二个plunker中,您正在分配来自$scope.vTypes的第二个选择/多重选择值。这是控制器中的全局变量,因此当您选择department进行修改后,function部分也会收到新值。

您需要的是每个过滤器vTypes

所以,在你的js中你可以这样做:

$scope.value = function(index, parent, field) {
    $scope.filters[index].vType = filterService.getValueType($scope.attribute[parent], $scope.comparisonType[field]);
}

在你的HTML中:

<td>
    <!--SELECT-->
    <select ng-if="item.check1==='2' && item.check2" 
           class="form-control" ng-model='item.check3' 
           ng-options='c as d.name for (c,d) in item.vType'>

        <option value='' disabled>Select...</option>
    </select>

    <!--MULTIPLE-->
    <select multiple ng-if="item.check1==='3'" 
            class="form-control" ng-model='item.check3' 
            ng-options='c as d.name for (c,d) in item.vType'>
    </select>
</td>

这是一个带有示例的plunkr: http://plnkr.co/edit/nL23ScGLBrqFuHp48ZsL?p=preview

答案 1 :(得分:0)

好吧,我认为你在指令中调用splice,但过滤器没有在指令中定义。你应该做的是将函数传递给指令。就像你已通过'过滤器'。这个'remove'函数可以在外部控制器上并作为

传递
scope: {
    filter: "=",
    removeFn: "&"
}

这样你可以在指令中触发这个函数并传递要删除的过滤器。

您也可以将所有过滤器传递给指令,然后将它们放在您的作用域中,然后使用您已经拥有的函数将它们从指令中删除

编辑:第二个解决方案,只需2行代码即可实现,但我不太喜欢它:

scope: {
    filter: "=",
    filters: "="
}

并在指令中添加

<tr data-ng-repeat="item in filters" class="text-center" filter="item" filters="filters">