进一步完成我的项目,但对数据绑定进行了打嗝。
我的数据更改未反映在DOM上
我在JS函数/对象中有一个构造函数。
constructor: function() {
var self = this;
var navigation = angular.module("navigation", []);
navigation.controller("ProductIDsController", function($scope) {
$scope.productIds = self.productIds;
});
angular.bootstrap(document.getElementById('navigation'), ['navigation']);
}
和产品ID在同一级别定义
productIds: ["abc", "xyz", "test"], //DOM gets populated from this array via angular
init: function(productIds) {
console.log(this.productIds); // displays ["abc", "xyz", "test"]
this.productIds.push("another item"); //this didn't work on the dom either
this.productIds = productIds; //I changed the productId's by passing another array
console.log(this.productIds); //the array got changed but DOM is still the same,
}
HTML
<div id="navigation">
<ul data-ng-controller="ProductIDsController">
<li data-ng-repeat="productId in productIds">{{productId}}</li>
</ul>
</div>
最初,DOM由给定的数组填充,但在我传入另一个数组后它没有改变。如何在给定方案中将数据绑定到productId?
编辑:JS小提琴
答案 0 :(得分:2)
你遇到了经典的Javascript错误,与AngularJS无关。在Javascript中,数组和对象总是通过引用传递。假设如下:
this.productIds = [1,2,3]
$scope.productIds = this.productIds;
这将创建一个数组,我们称之为“A”。然后它将在this.productIds和$ scope.productIds中引用该数组。
如果你现在这样做:
this.productIds = [4,5,6];
console.log(this.productIds);
console.log($scope.productIds);
然后你会得到:
[4,5,6]
[1,2,3]
为什么呢?因为设置this.productIds
不会更改数组。它会更改哪个数组this.productIds
POINTS TO。
有很多方法可以解决这个问题。这是一个快速黑客:
this.productIds.length = 0; // Truncate the existing array instead of making a new one
angular.forEach(productIds, function(entry) {
this.productIds.push(entry); // Copy the elements into our existing array
});
这不一定是最有效的,但它会告诉你到底发生了什么。
答案 1 :(得分:1)
当您更改范围之外的值时,您必须明确调用$scope.$apply()
。
https://docs.angularjs.org/guide/scope
<强>更新强>
http://jsfiddle.net/qv31awmq/2/
puremvc.define({
name: "modules.search.view.components.Navigation",
constructor: function () {
var self = this;
var navigation = angular.module("navigation", []);
navigation.controller("ProductIDsController", function ($scope) {
self.$scope = $scope;
$scope.productIds = self.productIds;
});
angular.bootstrap(document.getElementById('navigation'), ['navigation']);
}
}, {
delegate: null,
$scope: null,
productIds: ["abc", "xyz", "test"],
init: function (productIds) {
var self = this;
// http://stackoverflow.com/questions/25941124/angular-data-binding-with-passed-params/25941351#25941351
self.productIds.length = 0;
angular.forEach(productIds, function (entry) {
self.productIds.push(entry);
});
self.$scope.$apply();
}
}, {});
var nav = new modules.search.view.components.Navigation();
nav.init(['foo', 'bar']);
答案 2 :(得分:0)
我认为最好的方法是使用服务来广播productIds中的更改。
navigation.factory('ProductSvc',
['$rootScope', function($rootScope) {
return {
productIds : [],
changeProductIds: function(newIds){
this.productIds = newIds
$rootScope.$broadcast('changeIds');
}
}
}])
与服务相关联的控制器:
navigation.controller("ProductIDsController", ['ProductSvc'],
function($scope, productSvc) {
...
$scope.$on('changeIds', function() {
$scope.productIds = ProductSvc.productIds;
})
}
通过服务更改productId(例如,在处理用户输入的控制器中)
ProductSvc.changeProductIds(newIds)