AngularJS指令 - 如何等待指令模板完成渲染?

3

我正在尝试编写一个带有模板的指令。该模板渲染了一些DOM元素,我想要获取这些元素。然而,当我尝试在链接函数中检索DOM元素时,这些元素无法被找到。如果我在选择元素之前添加window.setTimeout方法,那么它们就会被找到。如何等待模板完成渲染后再尝试在链接函数中操作DOM?

以下是我想要实现的指令代码:

module.directive('testLocationPicker', function() {

    var linkFn = function(scope, element, attrs) {
        console.log('in linking function');
        window.setTimeout(function() {
            var positions = $('.position');
            console.log('number positions found: ' + positions.length);
            positions.click(function(e) {
                console.log('position clicked');
                scope.$apply(function() {
                     scope.selectedPosition = $(e.currentTarget).html();
                });
            });
        }, 500);
    };

    return {
        link: linkFn,
        restrict: 'E',        
        template: 'Choose a position: <div class="position" ng-repeat="position in positions">{{position}}</div>',        
    }        

});

我有一个JS Fiddle,里面有我想要完成的内容:http://jsfiddle.net/bdicasa/XSFpu/42/

2个回答

1
我建议改为这样做:
var module = angular.module('test', []);

module.controller('TestController', function($scope) {
    $scope.positions = [
        'Test Position 1',
        'Test Position 2',
        'Test Position 3'    
    ];

    $scope.selectedPosition = '';

    $scope.handleClick = function (index) {
        $scope.selectedPosition = $scope.positions[index];
    }
});        

module.directive('testLocationPicker', function() {    
    return {
        restrict: 'E',        
        template: 'Choose a position: <div class="position" ng-repeat="position in positions" ng-click="handleClick($index)">{{position}}</div>',        
    }        
});

虽然这样做很有道理,但我仍然不明白为什么我的点击处理程序没有在链接函数中注册?我以为在链接函数中访问DOM是安全的? - Brian DiCasa
在链接函数中访问DOM元素是安全的,但正如Macked所述,ng-repeat实际上还没有运行。您可以通过修改<div class="position"代码以包括ng-class="getClass($index)"来自行查看,然后在控制器中添加一个函数$scope.getClass = function(index) { console.log('class: ' + index); return 'position'; }; - Ryan O'Neill
1
好的,这很有道理。只是好奇你是否知道一个事件处理程序,在ng-repeat完成后会在指令中触发? - Brian DiCasa

1

不要试图搜索DOM并添加点击事件,只需像这样修改您的模板:

 template: 'Choose a position: <div class="position" ng-repeat="position in positions" data-ng-click="positionClick($index)">{{position}}</div>',

然后在链接函数中创建一个positionClick函数:
var linkFn = function(scope, element, attrs) {
    scope.positionClick = function(index){
     scope.selectedPosition = index;   
    }
};

可工作的jsFiddle: http://jsfiddle.net/XSFpu/77/

你的方法无法正常工作的原因是ng-repeat在模板加载后尚未触发。因此,它已经加载了指令,并且链接函数已被调用,但实际上ng-repeat尚未开始重复。这就是为什么我建议移动一些代码以适应这种情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接