角度数据与传递的参数绑定

时间:2014-09-19 19:30:14

标签: javascript angularjs

进一步完成我的项目,但对数据绑定进行了打嗝。

我的数据更改未反映在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小提琴

http://jsfiddle.net/casadev/n50ecw5m/

3 个答案:

答案 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)