如何从 AngularJS 指令中选择动态生成的元素? [英] How to select dynamically generated elements from inside an AngularJS directive?

查看:20
本文介绍了如何从 AngularJS 指令中选择动态生成的元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的指令中,我需要选择某些 DOM 元素,其中一些是在 ng-repeat 循环中动态生成的.如果我以一种直接的方式来做,我只会得到静态元素.但是,如果我将选择延迟 500 毫秒,我将获得所有元素,这正是我想要的.

尽管这有效,但它不是理想的解决方案,而且看起来也不是最佳实践.一方面,您希望使超时尽可能短,但另一方面,您希望在选择之前确保 DOM 已准备就绪.

是否有在所有动态 DOM 准备就绪时触发的事件?从 AngularJS 指令中选择动态生成的元素的推荐方法是什么?

示例:

HTML:

<div class="modal-body"><标签数据本地化>类型:</label>&nbsp;<select class="form-control" ng-model="assetFilter.appCode" ng-change="loadassets(assetFilter.appCode)" ng-options="type.code as type.name for type in types"></选择><table class="table table-default" ng-show="hasLoaded"><tbody ng-repeat="资产中的资产 | filter:assetFilter | orderBy:'assetKey':false"><tr><td><div class="container-fluid"><div class="row vert-align"><div class="col-sm-4">{{asset.assetKey}}

<div class="col-sm-8" style="height:100%"><input ng-hide="asset.assetKey.length >= 80" type="text" class="form-control" ng-model="asset.assetValue" ng-change="asset.isModified=true"><textarea ng-show="asset.assetKey.length > 80" class="form-control" ng-model="asset.assetValue" ng-change="asset.isModified=true"></textarea>

</td></tr></tbody>

<div class="modal-footer"><button class="btn btn-primary" ng-click="save(saveassets, $event)" ng-disabled="!(assets | anyModified)" data-localize>保存</button><button class="btn btn-warning" ng-click="close($event)" data-localize>关闭</button>

指令:

myApp.directive('myDirective', function ($timeout) {返回 {限制:'A',//仅属性链接:函数(范围,元素,属性,ctrl){var context = elem[0];var availableFormElements = 'input:not([disabled]):not([class*=ng-hide]),' +'select:not([disabled]):not([class*=ng-hide]), textarea:not([disabled]):not([class*=ng-hide]),' +'button:not([disabled]):not([class*=ng-hide]),' +'*[class*=btn]:not([disabled]):not([class*=ng-hide])';var allFormElements = context.querySelectorAll(availableFormElements);//只会获取静态元素,不会从 ng-repeat 循环中获取$超时(函数(){allFormElements = context.querySelectorAll(availableFormElements);//将包括所有元素,也来自 ng-repeat 循环}, 500);//操作选定表单元素的代码};});

解决方案

这是一个如何解决的简单示例.我认为此解决方案的唯一缺点是您不能使用隔离范围.

html

<div 外部指令><ul><li ng-repeat="资产中的资产"内部指令>{{资产}}<input type="text" class="form-control">

js

var app = angular.module('myApp', []);app.controller('MainController',function($scope) {$scope.assets = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];});app.directive('outerDirective', function() {返回 {限制:'A',控制器:功能($范围){}};});app.directive('innerDirective', function() {返回 {限制:'A',要求:'^outerDirective',链接:功能(范围,元素,属性,ctrl){var context = elem[0];如果(范围.$last){var availableFormElements = 'input,textarea';var allFormElements = context.querySelectorAll(availableFormElements);console.log(allFormElements);}}};});

或更好

.directive('myParent', function ($timeout) {返回 {限制:'A',//仅属性控制器:函数($scope,$element){this.isDone = function(){var context = $element[0];var availableFormElements = 'input,textarea';var allFormElements = context.querySelectorAll(availableFormElements);console.log(allFormElements);}}};}).directive('myChild', function ($timeout) {返回 {要求:'^myParent',限制:'A',//仅属性链接:函数(范围,元素,属性,ctrl){如果(范围.$last){ctrl.isDone();}}};})

顺便说一句不要触摸控制器中的 dom :)

In my directive, I need to select out certain DOM elements, some of which are generated dynamically in an ng-repeat loop. If I do it in a straightforward way, I will only get the static elements. However, if I delay the selection by, say, 500ms, I will get all elements, which is what I want.

Although this works, it is not an ideal solution, and certainly doesn't seem like best practise. On the one hand, you'd like to keep the timeout as short as possible, but on the other hand, you want to be sure that the DOM is ready before selecting.

Is there an event which fires when all dynamic DOM is ready? What is the recommended way to select dynamically generated elements from an AngularJS directive?

EXAMPLE:

HTML:

<div data-my-directive>
    <div class="modal-body">                        
        <label data-localize>type:</label>&nbsp;
        <select class="form-control" ng-model="assetFilter.appCode" ng-change="loadassets(assetFilter.appCode)" ng-options="type.code as type.name for type in types"></select>

            <table class="table table-default" ng-show="hasLoaded">
                <tbody ng-repeat="asset in assets | filter:assetFilter | orderBy:'assetKey':false">
                <tr>
                    <td>
                        <div class="container-fluid">
                            <div class="row vert-align">
                                <div class="col-sm-4">
                                    {{asset.assetKey}}
                                </div>
                                <div class="col-sm-8" style="height:100%">
                                    <input ng-hide="asset.assetKey.length >= 80" type="text" class="form-control" ng-model="asset.assetValue" ng-change="asset.isModified=true">
                                    <textarea ng-show="asset.assetKey.length > 80" class="form-control" ng-model="asset.assetValue" ng-change="asset.isModified=true"></textarea>
                                </div>
                            </div>
                        </div>
                    </td>
                </tr>
            </tbody>
        </table>

    </div>
    <div class="modal-footer">
        <button class="btn btn-primary" ng-click="save(saveassets, $event)" ng-disabled="!(assets | anyModified)" data-localize>Save</button>
        <button class="btn btn-warning" ng-click="close($event)" data-localize>Close</button>
    </div>
</div>

Directive:

myApp.directive('myDirective', function ($timeout) {
    return {
        restrict: 'A', //attribute only
        link: function (scope, elem, attr, ctrl) {    
            var context = elem[0]; 
            var availableFormElements = 'input:not([disabled]):not([class*=ng-hide]),' +
                'select:not([disabled]):not([class*=ng-hide]), textarea:not([disabled]):not([class*=ng-hide]),' +
                'button:not([disabled]):not([class*=ng-hide]),' +
                '*[class*=btn]:not([disabled]):not([class*=ng-hide])';

            var allFormElements = context.querySelectorAll(availableFormElements);
            // Will only get static elements, nothing from ng-repeat loop

            $timeout(function () {
                allFormElements = context.querySelectorAll(availableFormElements);
                // Will include all elements, also from ng-repeat loop
            }, 500);     

            // Code to manipulate selected form elements   

    };
});

解决方案

This is a simple example how you could work it out. Imo the only drawback to this solution is you can't use an isolate scope.

html

<div data-ng-controller="MainController">
    <div outer-directive>
        <ul>
            <li ng-repeat="asset in assets" inner-directive>
                      {{asset}}
                      <input type="text" class="form-control">
            </li>
        </ul>
    </div>
</div>

js

var app = angular.module('myApp', []);

app.controller('MainController',function($scope) {
    $scope.assets = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]; 
});

app.directive('outerDirective', function() {
  return {
    restrict: 'A',
    controller: function($scope) {

    }
  };
});
app.directive('innerDirective', function() {
  return {
    restrict: 'A',
    require: '^outerDirective',
    link: function(scope, elem, attrs,ctrl) {
        var context = elem[0]; 
        if (scope.$last){
            var availableFormElements = 'input,textarea';
            var allFormElements = context.querySelectorAll(availableFormElements);
            console.log(allFormElements);
        }
    }
  };
});

or better

.directive('myParent', function ($timeout) {
        return {
            restrict: 'A', //attribute only
            controller: function ($scope, $element) { 
                this.isDone = function(){
                    var context = $element[0]; 
                    var availableFormElements = 'input,textarea';
                    var allFormElements = context.querySelectorAll(availableFormElements);
                    console.log(allFormElements);
                }
            }
        };
    })
    .directive('myChild', function ($timeout) {
        return {
            require:'^myParent',
            restrict: 'A', //attribute only
            link: function (scope, elem, attr, ctrl) {    

                if (scope.$last){
                    ctrl.isDone();
                }
            }
        };
    })

BTW Don't touch the dom in the controller :)

这篇关于如何从 AngularJS 指令中选择动态生成的元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆