1

我有一个名为的地址数组addressesForUser。我还有一个带有隔离范围的“地址”指令。

当我这样做时:

<div ng-repeat="add in addressesForUser" entryid="{{ add.id }}">{{ add.id }}</div>            

一切都很好,对于三个地址,我得到以下生成的 html:

<div entryid="1">1</div>
<div entryid="2">2</div>
<div entryid="3">3</div>

但是当我这样做时:

<address ng-repeat="add in addressesForUser" entryid="{{ add.id }}"></address>

然后尝试console.log(attrs.entryid)在指令的链接函数中,我得到“add.id”作为输出中的字符串。更糟糕的是,生成的 html 中的属性是未定义的——只有属性名称存在——所以它既不是从 1 到 3 的数字,也不是字符串“add.id”。

我究竟做错了什么?最终目标是让每个地址指令读取其 entryid 属性,因此它可以独立自动填充并生成地址卡,或者如果缺少 entryid,它会显示一个输入新地址的表单。后一部分工作正常,但我不明白为什么它没有读取 entryid 值。

编辑:当我不使用隔离范围时(即我从指令中删除“范围:{}”),它可以工作。但是我需要隔离范围,所以我想我只需要一种方法来使属性包含在单个指令的范围内。这是一个稍微精简的地址指令代码:

myapp.directive('address', ['GeoService', '$http', function (gs, http) {
    return {
        restrict: 'E',
        templateUrl: 'address.html',
        scope: {
        },
        link: function (scope, element, attrs) {

            scope.emptyForm = {
                first_name: '',
                last_name: '',
                country: '',
                city: '',
                street: '',
                phone: '',
                is_def: '',
                zip: '',
                additional_info: '',
                residence_type: ''
            }

            console.log(attrs.entryid);

            scope.countries = gs.countries();
            scope.resetAddressForm = function(e) {
                scope.newAddressForm = scope.emptyForm;
            }
            scope.saveAddress = function() {
                http.post('/users/saveaddress', scope.newAddressForm).then(function (response) {

                   console.log(response.data); // Do something
                });
            }
            scope.$watch('newAddressForm.country', function(v) {
                if (v != undefined) {
                    scope.cities = gs.cities(v);
                }
            });
        }
    }
}]);
4

3 回答 3

2

这里的问题实际上是在指令中你不能假设link函数运行时属性已经准备好。如果该值是插值的,则您通常无法使用它。访问属性的规范方法是通过$observe

link: function ( scope, element, attrs ) {
  attrs.$observe( 'entryid', function ( val ) {
    // do something with the val
  });
}

如果您使用的是隔离范围,则为公共属性添加范围属性可能是一个好主意,但您仍然不应假定该值在link. $observe如果可能需要对值进行插值,则应始终使用该方法。

于 2013-05-28T05:11:17.230 回答
1

由于您的指令不会修改 的值add.id(因此您不需要双向数据绑定),我建议使用@而不是=. 一旦用 定义@,您可以使用attrs.$observe()scope.$watch()来获取插值:

scope: {
   entryid: '@',
},
link: function (scope, element, attrs) {
    attrs.$observe('entryid', function(value) {
        console.log('observed value=',value);
    });
    scope.$watch('entryid', function(value) {
       console.log('watched value=',value);
    });
    ...
}

fiddle

于 2013-06-04T01:30:10.277 回答
0

经过一番修修补补,我偶然得到了解决方案。该文档确实可以在这方面使用更多的工作。

本质上,隔离范围需要这样定义:

scope: {entryid: "="}

然后通过范围而不是通过 attrs 访问该值,如

console.log(scope.entryid);
于 2013-05-27T22:11:30.790 回答