动态添加Angular指令

时间:2013-12-09 22:54:56

标签: javascript angularjs angularjs-directive

我对角度JS相当新,并且发现它是一个陡峭的学习曲线,我觉得我真的错过了这里的重点但是这里有:

我想从控制器向我的页面添加一个指令。所以我想如果我将指令标签添加到页面,指令和相关的控制器/模板等都会添加它。在阅读了$ compile方法之后,我认为这将用于将此指令绑定到其新创建的标记。这部分在下面被注释掉了,但无论是否有这个,我需要登录这个词出现,它的控制器来控制它吗?

当加载时指针标记在页面上时,我可以在网上找到很多相似的例子,并且可以使这些例子正常工作,所以这就是认为它与$ compile方法有关 - 什么我错过了吗?

HTML:

<div ng-app="application" ng-controller="myController"></div>

JS:

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

myApp.controller('myController', ['$scope', function($scope) {

        function showLoginDirective () {
            $scope.login = angular.element(document.createElement('login'));

            angular.element(document.body).append($scope.login);
        };

        showLoginDirective();
    }
]);

angular.module('directives', [])
    .directive('login', function($compile) {
        return {
            restrict: 'E',
            controller: 'LoginController',
            template: '<div>login</div>',
            link: function(scope, element, attrs) {
                //$compile(element.contents())(scope.$new);
                console.log('should I not have a div containing login controlled by loginController at this point?');
            }
        };
});

上面的代码也在这里:http://jsfiddle.net/d5n6L/7/

3 个答案:

答案 0 :(得分:8)

您不应该使用Angular动态地向页面添加元素。很多人,包括我自己,都来自jQuery背景,他们假设我们可以继续这种做法,只需在我们需要的时候添加内容。

然而,对于Angular,逻辑应该在标记中完全可见。那是什么意思?在您的情况下,无论如何都应该有指令,然后使用ng-showng-hideng-class来控制其可见性。

所以,这样的事情是最好的:

<login ng-show="showLogin"></login>

然后你可以在编程时使用你的指令。

请注意,您还可以定义内联控制器(将依赖项数组和这些依赖项的函数指定为指令的controller属性)。这使得所有相关代码保持在同一个位置。

如,

angular.module('directives', [])
    .directive('login', function($compile) {
        return {
            restrict: 'E',
            controller: ['$scope', function($scope) {

                function showLoginDirective () {
                    $scope.showLogin = true;

                };

                 showLoginDirective();
              }
            ],
            template: '<div>login</div>',
            link: function(scope, element, attrs) {
                //$compile(element.contents())(scope.$new);
                console.log('should i not have a div containing login controlled by loginController at this point?');
            }
        };
});

答案 1 :(得分:4)

我建议您使用ng-if以声明方式表示DOM上应存在哪些DOM元素,而不是从控制器中动态编译。

HTML

<div ng-app="application" ng-controller="myController">
    <div ng-if="showLogin" login></div>
</div>

JS

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

myApp.controller('myController', ['$scope', function($scope) {

        function showLoginDirective () {
            $scope.showLogin = true;
        };

        showLoginDirective();
    }
]);

angular.module('directives', [])
    .directive('login', function($compile) {
        return {
            restrict: 'E',
            controller: 'LoginController',
            template: '<div>login</div>',
            link: function(scope, element, attrs) {
                //$compile(element.contents())(scope.$new);
                console.log('should i not have a div containing login controlled by loginController at this point?');
            }
        };
});

答案 2 :(得分:3)

  

我想从控制器向我的页面添加一个指令。

您应该能够在$ scope上定义一个布尔变量,用于确定是否显示登录名。

$scope.loginShouldBeShowing = false;
$scope.showLogin = function() {
  $scope.loginShouldBeShowing = true;
};

然后,您可以在模板中使用ngIf指令,仅在此变量设置为true时显示登录模板

<login ng-if="loginShouldBeShowing"></login>

您可以在

修改过的JSFiddle中看到这一点

http://jsfiddle.net/jK9zr/2/

我还添加了一个按钮,以便您可以在控制台中看到link功能仅在您按下按钮后运行,并且loginShouldBeShowing设置为true

  

当加载时指针标记在页面上时,我可以在网上找到很多相似的例子,并且可以使这些例子正常工作,所以这就是认为它与$ compile方法有关

根据我的理解和以前的使用,通常在模板中包含仅在某些情况下使用的指令,即当某些$ scope变量设置为某些值时,使用ngIf,或者ngSwitch或ngShow。我认为如果你试图$编译模板的任何一部分可能会或可能不会使用的每一部分,事情很快就会变得非常混乱。虽然我只是AngularJS的初学者,到目前为止,我只需要在评估自定义指令的属性时使用$ compile,所以

<login after-login="doThisFunction()"></login>
然后

可能需要使用$ compile在适当的时候调用doThisFunction()

作为一个小侧边栏,变量的名称有点说明在控制器中,您关注模板中发生的事情。在控制器中保留某种模型/业务“状态”更为常见,然后在模板中显示相应的内容。所以你可能在控制器中:

$scope.loginState = 'loggedOut';

然后在模板中:

<login ng-if="loginState == 'loggedOut'"></login>

编辑:我还注意到登录指令与应用程序的其余部分位于不同的模块中。我怀疑这会引起问题,所以我在JSFiddle中修改了这个方面,所以只有一个模块。

编辑:我觉得上面的$ compile和$ parse之间很困惑,所以我会查看有关我使用$ compile的文档/其他来源。