0

我有一个指令,它接受一个集合并构建一个下拉列表。

.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;
            });
        } ]
    }
});

这工作正常。它建立了下拉没有问题。当我更改下拉值时,第二个监视函数被调用,我可以看到它将集合选择的值设置为我想要的值。但是,我放入指令中的 collectionchoice 并没有绑定到新的选择。

<lookupDropdown collectionset="SecurityLevels" collectionchoice="AddedSecurityLevel"></lookupDropdown>

那就是 HTML 标记。

这是javascript:

$scope.SecurityLevels = new Array();
$scope.GetSecurityLevelData = function () {
    genericResource.setupResource('/SecurityLevel/:action/:id', { action: "@action", id: "@id" });
    genericResource.getResourecsList({ action: "GetAllSecurityLevels" }).then(function (data) {
        $scope.AddedSecurityLevel = data[0].SCRTY_LVL_CD;
        $scope.SecurityLevels = data;
        //have to get security levels first, then we can manipulate the rest of the page
        genericResource.setupResource('/UserRole/:action/:id', { action: "@action", id: "@id" });
        $scope.GetUserRoles(1, "");
    });
}
$scope.GetSecurityLevelData();

然后,当我发布我的新用户角色时,我将用户角色字段设置为:

 NewUserRole.SCRTY_LVL_CD = $scope.AddedSecurityLevel;

但这仍然是第一项,即使我已经更新了下拉列表,根据手表功能,它已更改为正确的值。我在这里想念什么?

4

2 回答 2

1

由于 Javascript 中的原型自然继承,您遇到了这个问题。让我试着解释一下。一切都是 Javascript 中的对象,一旦你创建了一个对象,它就会继承所有的 Object.Prototype(s),最终导致最终的对象,即 Object。这就是为什么我们能够 .toString() javascript 中的每个对象(甚至函数),因为它们都是从 Object 继承的。

这个关于指令的特殊问题是由于对 Angular JS 中的 $scope 的误解而产生的。$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只查看某处是否有一个点(。),如果它丢失,你可能做错了。

于 2014-05-25T18:56:10.020 回答
0

这里的问题是我的指令被嵌入到另一个指令中。使范围即时传递它所在指令的子级。所以类似于 $parent -> $child -> $child。这当然是对第三层和第二层进行更改。但是第一层不知道发生了什么。这修复了它:

<lookupDropdown collectionset="SecurityLevels" collectionchoice="$parent.AddedSecurityLevel"></lookupDropdown>
于 2013-09-10T20:56:40.870 回答