Я пытаюсь сделать динамичную форму в угловых 1.4.7, в котором:Угловые динамические выбирает есть пункты, которые влияют друг на друга
- Есть несколько отчетов (
vm.reports = [];
) - Каждый отчет может быть назначен ОДИНобъект via
vm.reportOptions
. - Каждый
vm.reportOptions
может быть выбран только ОДИН через несколько отчетов, которые фильтруются черезexclude
. - В каждом отчете поддерживается МНОГИЕ
dimension
Объекты viavm.dimensionOptions
. - Каждое измерение может быть выбрано только ОДИН за отчет, который фильтруется через
excludeDimensions
(последующие отчеты имеют доступ ко всемdimensionOptions
и фильтруют сами).
Эти требования все работают (примерно) за исключением:
- Если добавить два отчета, и добавьте точно такие же размеры (то есть: Report One>Размеры Один>Включить размерный фильтр и Report Two>Размеры Один>Включить размерный фильтр) для каждого из отчетов, изменяя выбор внутри Включить фильтр размеров изменяет его в обоих отчетах.
Я предполагаю, что это происходит из-за того, что я раздвигают реальные объекты измерения и отчета каждой dimensions: []
массива, и что они по-прежнему указывают на тот же объект.
- редактирует -
Я понимаю angular.clone()
это хороший способ разорвать эту ссылку, но <select>
кода, который я написал автоматически конвейеру в объекте к модели. У меня возникло соблазн дать каждому отчету собственный контроллер и дать каждому отчету свои 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;
};
}]);
Да, я делаю это первоначально, когда поставляемые значения будут отправляться через «службу». Но как сделать копию 'formObject' при выбранном изменении? Прямо сейчас, выбор из списка делает все это волшебство для меня. – tr3online
У меня возникло соблазн использовать контроллер для каждого отчета, и у них есть только собственный контекст. Это хорошее решение? – tr3online
может скопировать элемент, чтобы отредактировать его, также если вы не хотите обновлять обновленную модель до сохранения ..... затем используйте 'angular.extend()' для слияния изменений в живую модель – charlietfl