javascript - Angular 动态选择具有相互影响的项目

标签 javascript angularjs angularjs-ng-repeat immutability

我正在尝试在 Angular 1.4.7 中创建一个动态表单,其中:

  • 有多个报告 ( vm.reports = []; )
  • 每个报告都可以通过 vm.reportOptions 分配一个报告对象
  • 每个vm.reportOptions只能在多个报告中选择一次,通过 exclude 进行过滤.
  • 每个报告支持许多 dimension 对象通过 vm.dimensionOptions .
  • 每个维度只能在每个报告中选择一次,并通过 excludeDimensions 进行过滤(后续报告可以访问所有 dimensionOptions 并自行过滤)。

这些要求都有效(大致),除了:

  • 如果我添加两个报告,并添加完全相同维度(即:报告一> 维度一> 启用维度过滤器报告二> 维度一> 启用维度过滤器)为每个报告,更改内部的选择>启用维度过滤器会在两个报告中更改它。

我认为发生这种情况是因为我将实际维度对象插入每个报告 dimensions: []数组并且它们仍然指向同一个对象。

-- 编辑 --

我意识到angular.clone()是打破此引用的好方法,但是 <select>我编写的代码会自动将对象通过管道传输到模型。我很想为每个报告提供自己的 Controller ,并为每个报告提供自己的 copy()选项。

这行得通吗?或者有更好的方法吗?

我有一个工作JSBin here .

相关代码:

HTML:

<body ng-app="app">

  <div ng-controller="AlertsController as alerts">

    <pre>{{alerts.output(alerts.reports)}}</pre>

    <div class="container">

    <div
      ng-repeat="report in alerts.reports"
      class="report"
    >
      <button
        ng-if="$index !== 0"
        ng-click="alerts.removeItem(alerts.reports,report)"
      >Delete Report</button>

      <label>Select Report</label>
      <select
        ng-model="alerts.reports[$index].report"
        ng-init="report"
        ng-options="reportSelect.niceName for reportSelect in alerts.reportOptions | exclude:'report':alerts.reports:report"
      ></select>

      <div
        ng-repeat="dimension in report.dimensions"
        class="condition"
      >
        <div class="select">
          <h1 ng-if="$index === 0">IF</h1>
          <h1 ng-if="$index !== 0">AND</h1>
          <select
            ng-model="report.dimensions[$index]"
            ng-change="alerts.checkThing(report.dimensions,dimension)"
            ng-init="dimension"
            ng-options="dimensionOption.niceName for dimensionOption in alerts.dimensionOptions | excludeDimensions:report.dimensions:dimension"
          >
            <option value="123">Select Option</option>
          </select>
          <button
            class="delete"
            ng-if="$index !== 0"
            ng-click="alerts.removeItem(report.dimensions,dimension)"
          >Delete</button>
        </div>


        <input type="checkbox" ng-model="dimension.filtered" id="filter-{{$index}}">
        <label class="filter-label" for="filter-{{$index}}">Enable Dimension Filter</label>

        <div ng-if="dimension.filtered">
          <select
            ng-model="dimension.operator"
            ng-options="operator for operator in alerts.operatorOptions">
          </select>
          <input
            ng-model="dimension.filterValue"
            placeholder="Text" 
          ></input>
        </div>

      </div>

      <button
        ng-click="alerts.addDimension(report)"
        ng-if="report.dimensions.length < alerts.dimensionOptions.length"
      >Add dimension</button>
    </div>

    <button
      ng-if="alerts.reports.length < alerts.reportOptions.length"
      ng-click="alerts.addReport()"
    >Add report</button>

    <!--
      <div ng-repeat="sel in alerts.select">
      <select ng-model="alerts.select[$index]" ng-init="sel" 
        ng-options="thing.name for thing in alerts.things | exclude:alerts.select:sel"></select>
    </div>
    -->

    </div><!-- container -->

  </div>

</body>

JS:

var app = angular.module('app', []);

app.controller('AlertsController', function(){
  var vm = this;

  vm.reportOptions = [
    {id: 1, niceName: 'Report One'},
    {id: 2, niceName: 'Report Two'},
    {id: 3, niceName: 'Report Three'},
  ];
  vm.dimensionOptions = [
    {id: 1, niceName: 'Dimension One'},
    {id: 2, niceName: 'Dimension Two'},
    {id: 3, niceName: 'Dimension Three'},
  ];
  vm.operatorOptions = [
    '>',
    '>=',
    '<',
    '<=',
    '=',
    '!='
  ];

  ////// DEBUG STUFF //////
  vm.output = function(value) {
    return JSON.stringify(value, undefined, 4);
  }
  ////////////////////////


  vm.reports = [];
  vm.addReport = function() {
    vm.reports.push({report: {id: null}, dimensions: []});
  }

  vm.removeItem = function(array,item) {
    if(array && item) {
      var index = array.indexOf(item);
      if(index > -1) {
        array.splice(index,1);
      }
    }
  }

  vm.addDimension = function(report) {
    console.log('addDimension',report);
    if(report) {
      report.dimensions.push({})
    }
  };

  // init
  if(vm.reports.length === 0) {
    vm.reports.push({report: {}, dimensions: [{}]});
//     vm.reports.push({report: vm.reportOptions[0], dimensions: [vm.dimensionOptions[0]]}); 
  }

});

app.filter('excludeDimensions', [function() {
  return function(input,select,selection) {
//     console.log('ed',input,select,selection);
    var newInput = [];
    for(var i = 0; i < input.length; i++){
      var addToArray=true;
      for(var j=0;j<select.length;j++){
          if(select[j].id===input[i].id){
              addToArray=false;
          }
      }
      if(addToArray || input[i].id === selection.id){
        newInput.push(input[i]);
      }
    }
    return newInput;
  }
}]);

app.filter('exclude', [function () {
  return function(input,type,select,selection){
    var newInput = [];
    for(var i = 0; i < input.length; i++){
      var addToArray=true;
      for(var j=0;j<select.length;j++){
          if(select[j][type].id===input[i].id){
              addToArray=false;
          }
      }
      if(addToArray || input[i].id === selection[type].id){
        newInput.push(input[i]);
      }
    }
    return newInput;
  };
}]);

最佳答案

How do I get around pushing same object reference to array

使用angular.copy()

array.push(angular.copy(vm.formObject));
// clear object to use again in form
vm.formObject={};

关于javascript - Angular 动态选择具有相互影响的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33005101/

相关文章:

javascript - 从元素的兄弟元素中选择一个元素

Javascript, jquery 错误 TypeError : $(. ..).autocomplete is not a function

angularjs - 如何从 AngularJS 异步验证器返回错误上下文信息?

javascript - 在 Angular JS 中 - 如何使用 ng-include 使我的代码通用且可重用?

javascript - angularJS:为什么绑定(bind)到指令内的范围会导致 ng-repeat 的内容丢失?

javascript - javascript 文件中的字符编码

javascript - Angular 应用程序不会处理 MongoDB 对象

javascript - Angular JS 中的 $http.get API

javascript - Angular JS 中 ng-repeat 中的数据绑定(bind)

javascript - 无法使用 mysql 包从我的 node.js 应用程序连接到数据库