【问题标题】:Angular ng-repeat with directive (in a cascaded repeat table)带有指令的 Angular ng-repeat(在级联重复表中)
【发布时间】:2017-08-29 21:17:49
【问题描述】:

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

我创建了两个“plunker”来展示我的问题。

  1. 带有自定义指令(用于 ng-repeat) (http://plnkr.co/edit/J8k74C3AUIAxv6rEKcWL?p=preview)
  2. 相同但没有指令 (http://plnkr.co/edit/neOgWfuyuFnkawRGJB0c?p=preview)

示例 2 中,当在 R1C1 中选择“功能”时,在 R1C2 中选择了一个随机选项,然后 R1C3 填充了级联选项。

在同一个示例中,当添加一行 (R2) 并在 R2C1 中选择“部门”并且在 R2C2 中选择另一个随机选项时,R2C3 会填充级联选项但是... R1C3 也会发生变化...

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

PLUNKER 代码(示例 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>

【问题讨论】:

    标签: javascript angularjs


    【解决方案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

    【讨论】:

    • 谢谢!我也试图支持你的回答,但我是新手(我收到一条消息,它已记录但不公开可见)。
    【解决方案2】:

    好的,我认为您在指令中调用 splice,但过滤器未在指令中定义。您应该做的是将函数也传递给指令。就像您通过了“过滤器”一样。这个“删除”功能可以在外部控制器上并作为

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

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

    您还可以将所有过滤器传递给指令,然后将它们放在您的范围内,然后使用您已经拥有的功能将它们从指令中删除

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

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

    并在指令中添加

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

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 2014-10-26
      • 2016-07-07
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-18
      相关资源
      最近更新 更多