如何从指令部分调用 ng-click? [英] How to invoke ng-click from a directive partial?

查看:34
本文介绍了如何从指令部分调用 ng-click?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有局部作用域的指令,其中部分包含 ng-click.

小提琴就在那里:http://jsfiddle.net/stephanedeluca/QRZFs/13/

不幸的是,由于我将代码移到指令中,ng-click 不再触发.

控制器和指令如下:

var app = angular.module('myApp', ['ngSanitize']);app.directive('plantStages', function ($compile) {返回 {限制:'E',转置:真实,模板:'<figure class="cornStages">\<p ng-transclude style="color: skyblue"></p>\<小时/>\<p ng-bind-html="标题"></p>\<p ng-bind-html="subtitle">{{subtitle}}</p>\<ul>\<li ng-repeat="stage in stage" ng-click="changePage(stage)">{{stage}}</li>\</ul>\</图>',范围: {阶段:"=",标题:'@'},链接:函数(范围、元素、属性、ctrl、transclude){if (!attrs.title) scope.title = "默认标题";}};});app.controller('myCtrl', function ($scope, $location, $http) {$scope.stages = ['floraison', 'montaison'];$scope.changePage = 函数(页面){var url = "corn.page.html#/"+page;console.log("更改页面 "+page+" 为 url "+url);alert("即将换页如下:document.location.href = "+url);};});

调用它的html如下:

阶段,<p ng-repeat="stage in stage">{{stage}}</p><小时/>植物阶段<植物阶段title="<b>探索<br/>du cycle</b>"subtitle="<em>这是一个<br/>副标题</em>"阶段=阶段">内部<br/>指令</植物阶段>

有什么想法吗?

您不能直接从指令访问控制器作用域中定义的 changePage(),因为您的指令具有独立的作用域.但是,仍然有几种方法可以做到:

选项 1:

选项 1 是最简单的选项.然而,它很像一种解决方法,我不建议广泛使用它.您可以从传递给链接函数的元素中获取控制器的范围,并在那里调用 changePage:

link: function (scope, element, attrs, ctrl, transclude) {if (!attrs.title) scope.title = "默认标题";scope.changePage = element.scope().changePage;//<= 从元素获取父作用域,它将有 changePage()}

选项 2:

如果您没有任何涉及在外部控制器中定义的范围的逻辑(如您的示例中所示),您可以为指令定义内部控制器并在那里执行:

app.directive('plantStages', function ($compile) {返回 {...控制器:['$scope',函数($scope){$scope.changePage = 函数(页面){var url = "corn.page.html#/"+page;console.log("更改页面 "+page+" 为 url "+url);alert("即将换页如下:document.location.href = "+url);}}]};});

选项 3:

如果您想在不同的指令和控制器中重用 changePage() 中定义的逻辑,最好的方法是将逻辑移动到某些可能同时注入控制器和指令的服务中:

app.service('changePageService', function() {this.changePage = 函数(页面){var url = "corn.page.html#/"+page;console.log("更改页面 "+page+" 为 url "+url);alert("即将换页如下:document.location.href = "+url);}});app.controller('myCtrl', function ($scope, $location, $http, changePageService) {...changePageService.changePage('page');...});app.directive('plantStages', function ($compile) {...控制器:['$scope','changePageService',函数($scope,changePageService){$scope.changePage = changePageService.changePage;}]...});

选项 4:

您可以将诸如 changePage(page) 之类的代码作为指令的某些属性的值传递,并且内部指令使用 '&' 定义范围属性,这将创建将在外部控制器的范围内执行的函数,参数传递给该函数.示例:

JavaScript

app.directive('plantStages', function ($compile) {返回 {限制:'E',转置:真实,模板:'<figure class="cornStages">\<p ng-transclude style="color: skyblue"></p>\<小时/>\<p ng-bind-html="标题"></p>\<p ng-bind-html="字幕"></p>\<ul>\<li ng-repeat="stage in stage" ng-click="changePage({page: stage})">{{stage}}

HTML

阶段,<p ng-repeat="stage in stage">{{stage}}</p><小时/>植物阶段<植物阶段title="<b>探索<br/>du cycle</b>"subtitle="<em>这是一个<br/>副标题</em>"阶段=阶段"更改页面=更改页面(页面)">内部<br/>指令</植物阶段>

Plunker: http://plnkr.co/edit/s4CFI3wxs0SOmZVhUkC4?p=preview

I have a directive that has a local scope where a partial contains ng-click.

The Fiddle is there: http://jsfiddle.net/stephanedeluca/QRZFs/13/

Unfortunatelly, since I moved my code to the directive, ng-click does not fire anymore.

The controller and the directive is as follows:

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

app.directive('plantStages', function ($compile) {
    return {
        restrict: 'E',
        transclude: true,
        template: '<figure class="cornStages">\
                        <p ng-transclude style="color: skyblue"></p>\
                        <hr/>\
                        <p ng-bind-html="title"></p>\
                        <p ng-bind-html="subtitle">{{subtitle}}</p>\
                        <ul>\
                            <li ng-repeat="stage in stages" ng-click="changePage(stage)">{{stage}}</li>\
                        </ul>\
                    </figure>',
        scope: {
            stages:"=",
            title:'@'
        },
        link: function (scope, element, attrs, ctrl, transclude) {
            if (!attrs.title) scope.title = "Default title";
        }
    };
});

app.controller('myCtrl', function ($scope, $location, $http) {
    $scope.stages = ['floraison', 'montaison'];
    $scope.changePage = function (page) {
        var url = "corn.page.html#/"+page;
        console.log("Change page "+page+" with url "+url);
        alert("about to change page as follows: document.location.href = "+url);
    };

});

The html that invokes it is as follows:

<div ng-controller="myCtrl">
    Stages, 
    <p ng-repeat="stage in stages">{{stage}}</p>
    <hr/>
    Plant stages
    <plant-stages 
        title="<b>Exploration<br/>du cycle</b>"
        subtitle="<em>This is a<br/>sub title</em>"
        stages="stages"
    >
        Inner<br/>directive
    </plant-stages>
</div>

Any idea?

解决方案

You can't access changePage() defined in controller's scope from directive directly, since your directive has isolated scope. However, there are still several ways to do it:

Option 1:

Option 1 is the most simple option. However it is much like a workaround and I don't recommend to use it widely. You can get your controller's scope from element passed to link function and invoke changePage there:

link: function (scope, element, attrs, ctrl, transclude) {
    if (!attrs.title) scope.title = "Default title";
    scope.changePage = element.scope().changePage; // <= Get parent scope from element, it will have changePage()
}

Option 2:

If you don't have any logic that involves scope defined in the outer controller (as in your example), you can define inner controller for your directive and perform it there:

app.directive('plantStages', function ($compile) {
    return {
       ...
       controller: ['$scope', function($scope) {
           $scope.changePage = function(page) {
               var url = "corn.page.html#/"+page;
               console.log("Change page "+page+" with url "+url);
               alert("about to change page as follows: document.location.href = "+url);
           }
       }]
    };
});

Option 3:

If you want do reuse logic defined in changePage() in different directives and controllers, the best way to do it is to move the logic to some service that may be injected to both controller and directive:

app.service('changePageService', function() {
    this.changePage = function(page) {
        var url = "corn.page.html#/"+page;
        console.log("Change page "+page+" with url "+url);
        alert("about to change page as follows: document.location.href = "+url);
    }
});

app.controller('myCtrl', function ($scope, $location, $http, changePageService) {
    ...
    changePageService.changePage('page');
    ...
});

app.directive('plantStages', function ($compile) {
    ...
    controller: ['$scope', 'changePageService', function($scope, changePageService) {
        $scope.changePage = changePageService.changePage;
    }]
    ...
});

Option 4:

You can pass piece of code like changePage(page) as value of some attribute of the directive and inside directive define scope property with '&' that will create a function that will be executed in the outer controller's scope with arguments passed to that function. Example:

JavaScript

app.directive('plantStages', function ($compile) {
    return {
        restrict: 'E',
        transclude: true,
        template: '<figure class="cornStages">\
                        <p ng-transclude style="color: skyblue"></p>\
                        <hr/>\
                        <p ng-bind-html="title"></p>\
                        <p ng-bind-html="subtitle"></p>\
                        <ul>\
                            <li ng-repeat="stage in stages" ng-click="changePage({page: stage})">{{stage}}</li>\
                        </ul>\
                    </figure>',
        scope: {
            stages:"=",
            title:'@',
            changePage:'&'
        },
        link: function (scope, element, attrs, ctrl, transclude) {
            if (!attrs.title) scope.title = "Default title";
        }
    };
});

HTML

<div ng-controller="myCtrl">
    Stages, 
    <p ng-repeat="stage in stages">{{stage}}</p>
    <hr/>
    Plant stages
    <plant-stages 
        title="<b>Exploration<br/>du cycle</b>"
        subtitle="<em>This is a<br/>sub title</em>"
        stages="stages"
        change-page="changePage(page)"
    >
        Inner<br/>directive
    </plant-stages>

Plunker: http://plnkr.co/edit/s4CFI3wxs0SOmZVhUkC4?p=preview

这篇关于如何从指令部分调用 ng-click?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆