给定一个数组sourceArray
我想创建一个targetArray
,它取决于第一个的条目。这意味着创建的Array应包含每个源条目的条目,并在sourceArray
更改时更新。但是,修改targetArray
永远不应该更新源。
只要sourceArray
是静态的,Plunker种就可以了。一旦你开始修改源条目,它显然不会正确更新目标,因为我缺乏适当的数据绑定机制。
我是否需要通过观察targetArray
手动更新sourceArray
或者是否有任何一种由Angular实现的单向数据绑定机制,我可以使用它来保持两个数组同步?
答案 0 :(得分:3)
正如普里塔姆所说。你应该使用$ watch。但必须将Collection绑定到它,以使其工作。在手表里面合并阵列。
找到这个工作样本:
$scope.$watchCollection(angular.bind(this, function () {
return this.sourceArray;}), function (newVal, oldVal) {
var arr = [];
for(var i in vm.sourceArray){
var shared = false;
for (var j in vm.targetArray)
if (vm.targetArray[j].id == vm.sourceArray[i].id) {
shared = true;
break;
}
if(!shared) arr.push(vm.sourceArray[i])
}
console.log(arr);
vm.targetArray = vm.targetArray.concat(arr);
},true);
答案 1 :(得分:1)
您应该使用$watch
。然后添加必要的功能。
您可以查看here和official documentation.
$ watch(watchExpression,listener,[objectEquality]);注册a 只要watchExpression发生变化,就会执行监听器回调。
每次调用$ digest()时都会调用watchExpression 返回将要观看的值。 (watchExpression不应该 使用相同的输入多次执行时更改其值 因为它可能会被$ digest()多次执行。那是, watchExpression应该是幂等的。)只调用监听器 当来的值来自当前的watchExpression和之前的调用 观察表达不相等(除了初始 跑,见下文)。不平等是根据参考确定的 不等式,通过!== Javascript运算符进行严格比较,除非 objectEquality == true(参见下一点)当objectEquality == true时, watchExpression的不等式是根据的确定的 angular.equals函数。保存对象的值以供日后使用 比较,使用angular.copy函数。因此这意味着 观看复杂的物体会产生不良的记忆和表现 影响。这不应该用于监视对象的变化 由于angular.copy的限制,它是或包含File对象。 手表监听器可能会更改模型,这可能会触发其他模型 听众要开火。这是通过重新运行观察者直到没有 检测到更改。重新运行迭代限制为10以防止 无限循环死锁。如果您想在$ digest时收到通知 调用,你可以注册一个没有监听器的watchExpression函数。 (准备多次调用watchExpression,因为它 如果发生变化,将在单个$摘要周期中多次执行 检测。)
在观察者注册范围后,监听器fn是 异步调用(通过$ evalAsync)来初始化观察者。在 在极少数情况下,这是不可取的,因为在何时调用侦听器 watchExpression的结果没有改变。检测这种情况 在监听器fn中,您可以比较newVal和oldVal。如果 这两个值是相同的(===)然后监听器被调用 初始化。
答案 2 :(得分:1)
您可以使用$ watch表达式。
这是另一种方式:-(下载underscore.js或CDN)
http://plnkr.co/edit/hrOrEdaQ0M7wEgWlRHlO?p=preview
underscore.js扩展方法。
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.sourceArray = [{id: '0', name: 'someObject'}, {id: '1', name: 'anotherObject'}];
vm.targetArray = angular.copy(vm.sourceArray);
// angular.copy(vm.sourceArray, vm.targetArray);
vm.push = function(){
let found = false;
angular.forEach(vm.sourceArray, function(el){
if (el.id === vm.id){
el.name = vm.name;
found = true;
}
});
if (!found){
vm.sourceArray.push({id: vm.id, name: vm.name});
_.extend(vm.targetArray, vm.sourceArray);
}
};
vm.pushTarget = function(){
let found = false;
angular.forEach(vm.targetArray, function(el){
if (el.id === vm.id1){
el.name = vm.name1;
found = true;
}
});
if (!found){
console.log({id: vm.id, name: vm.name})
vm.targetArray.push({id: vm.id1, name: vm.name1});
}
};
});
你可以获得underscore.js代码: -
_.extend = createAssigner(_.allKeys);
// An internal function for creating assigner functions.
var createAssigner = function(keysFunc, undefinedOnly) {
return function(obj) {
var length = arguments.length;
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// Retrieve all the property names of an object.
_.allKeys = function(obj) {
if (!_.isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Extend a given object with all the properties in passed-in object(s).
答案 3 :(得分:1)
这是我制作的片段。请注意,更改源阵列时,两个阵列都会受到影响,但是当您仅更改目标时,源保持不变。
angular.module('app', [])
.controller('mainCtrl', function($scope) {
var vm = this;
vm.sourceArray = [];
vm.source = '["change me!",{"a":3},[100]]';
$scope.$watch('vm.source', function(newVal) {
try {
vm.sourceArray = JSON.parse(newVal);
vm.target = newVal;
vm.serr = null;
} catch (e) {
vm.serr = 'Invalid JSON';
}
});
$scope.$watch('vm.target', function(newVal) {
try {
vm.targetArray = JSON.parse(newVal);
vm.terr = null;
} catch (e) {
vm.terr = 'Invalid JSON';
}
});
//Copy whole array on change
$scope.$watch('vm.sourceArray', function(newVal) {
vm.targetArray = angular.copy(newVal);
}, true);
return this;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="mainCtrl as vm">
<span>Change the inputs one at a time to see the changes take effect</span>
<h5>Source:</h5>
<input type="text" ng-model="vm.source" ng-model-options="{debounce: 300}" placeholder="Enter json formatted string for source array"><span>{{vm.serr}}</span>
<div>Model: {{vm.sourceArray|json:null:2}}</div>
<br>
<h5>Target:</h5>
<input type="text" ng-model="vm.target" ng-model-options="{debounce: 300}" placeholder="Enter json formatted string for source array"><span>{{vm.terr}}</span>
<div>Model: {{vm.targetArray|json:null:2}}</div>
</div>