Javascript ui-select2内部指令isn';t更新控制器模型

Javascript ui-select2内部指令isn';t更新控制器模型,javascript,angularjs,angularjs-directive,angular-ui,ui-select2,Javascript,Angularjs,Angularjs Directive,Angular Ui,Ui Select2,我有一个指令,它接收一个集合并生成一个下拉列表 .directive("lookupdropdown", function () { return { restrict: 'E', scope: { collectionset: '=', collectionchoice: '=' }, replace: true, template: '<select

我有一个指令,它接收一个集合并生成一个下拉列表

.directive("lookupdropdown", function () {
    return {
        restrict: 'E',
        scope: {
            collectionset: '=',
            collectionchoice: '='
        },
        replace: true,
        template: '<select class="input-large" ui-select2 ng-model="collectionchoice" data-placeholder="">' +
                    '    <option ng-repeat="collection in repeatedCollection" value="{{collection.id}}">{{collection.description}}</option>' +
                    '</select>',
        controller: ["$scope", function ($scope) {
            $scope.repeatedCollection = new Array(); //declare our ng-repeat for the template
            $scope.$watch('collectionset', function () {
                if ($scope.collectionset.length > 0) {
                    angular.forEach($scope.collectionset, function (value, key) { //need to 'copy' these objects to our repeated collection array so we can template it out
                        $scope.repeatedCollection.push({ id: value[Object.keys(value)[0]], description: value[Object.keys(value)[1]] });
                    });
                }
            });

            $scope.$watch('collectionchoice', function (newValue, oldValue) {
                debugger;
                $scope.collectionchoice;
            });
        } ]
    }
});
然后,当我发布我的新用户角色时,我将用户角色字段设置为:

 NewUserRole.SCRTY_LVL_CD = $scope.AddedSecurityLevel;

但这仍然是第一项,即使我更新了下拉列表,根据watch函数,它已更改为正确的值。我在这里遗漏了什么?

这里的问题是我的指令被另一个指令所包含。使作用域传入它所在的指令的子级。比如$parent->$child->$child。这当然是对第三层和第二层进行更改。但是第一层不知道发生了什么。这修正了它:

<lookupDropdown collectionset="SecurityLevels" collectionchoice="$parent.AddedSecurityLevel"></lookupDropdown>

您面临这个问题是因为Javascript中的原型本质继承。让我试着解释一下。在Javascript中,一切都是一个对象,一旦你创建了一个对象,它就会继承所有的object.Prototype,这最终导致最终的对象,即object。这就是为什么我们能够在javascript中对每个对象(甚至函数)使用.toString(),因为它们都是从对象继承的

关于指令的这个特殊问题是由于对JS中$scope的误解而产生的$范围不是模型,而是模型的容器。有关在$scope上定义模型的正确和错误方法,请参见下文:

...
$scope.Username = "khan@gmail.com"; //Incorrect approach
$scope.Password = "thisisapassword";//Incorrect approach
...
$scope.Credentials = {
    Username: "khan@gmail.com", //Correct approach
    Password: "thisisapassword" //Correct approach
}
...
这两个声明有很大区别。当您的指令更新其作用域(指令的隔离作用域)时,它实际上使用新值完全消除了引用,而不是更新对父作用域的实际引用,因此它断开了指令作用域和控制器的连接

你的做法如下:

<lookupDropdown collectionset="SecurityLevels" collectionchoice="$parent.AddedSecurityLevel"></lookupDropdown>

这种方法的问题是,虽然它可以工作,但它不是推荐的解决方案,原因如下。如果您的指令被放置在另一个指令中,在指令的作用域和实际控制器之间有另一个隔离的作用域,那么在这种情况下,您必须执行
$parent.$parent.AddedSecurityLevel
,这可能会永远持续下去。因此,这不是一个推荐的解决方案

结论:

始终确保在作用域上有一个定义模型的对象,无论何时使用隔离作用域或使用使用隔离作用域的ng指令,即
ng model
,只要看看某处是否有一个点(.),如果缺少,则可能是做错了

...
$scope.Username = "khan@gmail.com"; //Incorrect approach
$scope.Password = "thisisapassword";//Incorrect approach
...
$scope.Credentials = {
    Username: "khan@gmail.com", //Correct approach
    Password: "thisisapassword" //Correct approach
}
...
<lookupDropdown collectionset="SecurityLevels" collectionchoice="$parent.AddedSecurityLevel"></lookupDropdown>