【问题标题】:Controller to Directive and Directive to controller correct way of communcation控制器对指令和指令对控制器的正确通信方式
【发布时间】:2015-07-05 10:20:27
【问题描述】:

我有一个页面,其中包含带有页面显示内容的pageNavigator。根据用户click 在相应按钮(链接)上的说法,我正在更新页面。

我将 :page navigator 的指令设为“docNavigation”并包含在我的home html 中。

现在我要求,

当页面加载时,

  1. 我的文档页面应该显示count,就像我在homeController 中提到的一样,最后一个switch 应该设置为20,我在homeController 中设置。

  2. 当用户交互时,我想更新homeController 中的count 以更新页面内容。

得到这个的正确方法是什么?

这是我的指令:

"use strict";

angular.module("docNaviDir", [])
    .directive("docNavigation", function () {
        return {
            restrict : "E",
            replace : true,
            templateUrl : '/views/directiveViews/docNavigation.html',
            link : function (scope, element, attr, controller) {
               var count = 0;
                element.find('a').on('click', function () {

                    var Id = $(this).prop('id');
                    switch(Id) {
                        case 'first':
                            count = 1; //update to `homeController`
                            break;
                        case 'prev':
                            count -= 1;  //update to `homeController`
                            break;
                        case 'next':
                            count += 1;  //update to `homeController`
                            break;
                        case 'last':
                            count = scope.totalPages; //get from `homeController`
                            break;
                    }
                scope.$apply(function () {
                    count = count;
                })
                })
            }
        }
    })

我的家庭控制器:

“用户严格”;

angular.module("ngTenderDocument")
    .controller('homeController', function ($scope) {
        $scope.count = 0; //pass to directive and update by user
        $scope.totalPages = 20; //pass to directive
    })

我的观点:

<doc-navigation></doc-navigation> //directive
<h1>This is from home! Now you start to count, count is : {{count}}</h1> //count need to show the appropriate updates here.

我的导航视图:

<nav class="navbar navbar-inverse">
    <ul class="nav navbar-nav">
        <li class="active"><a id="first" href="#">First</a></li>
        <li><a id="prev" href="#">Previous</a></li>
        <li><a id="next" href="#">Next</a></li>
        <li><a id="last" href="#">Last</a></li>
    </ul>
</nav>

【问题讨论】:

  • 我假设 HomeController 将始终在屏幕上?
  • 不,这仅适用于home.html 视情况而定。
  • 让我重新表述我的问题:导航栏是否总是在 HomeController 可用的屏幕上使用?如果没有,您打算如何在其他屏幕上实现此分页?
  • 其实这是主屏幕的一个子屏幕。这个屏幕只有pagenavigation 更新了html 内容。 (这个页面本身就是另一个页面的内容)

标签: jquery angularjs angularjs-scope angular-directive


【解决方案1】:

使用隔离作用域并将计数值从指令属性传递给它。在隔离范围内,您需要提及scope: { count: '=' },,它将执行与count 属性中指定的控制器变量和directive 计数变量的双向绑定。

标记

<doc-navigation count="count"></doc-navigation>

指令

angular.module("docNaviDir", [])
    .directive("docNavigation", function () {
        return {
            restrict : "E",
            replace : true,
            scope: {
              count: '=' //specified two way binding here
            },
            templateUrl : '/views/directiveViews/docNavigation.html',
            link : function (scope, element, attr, controller) {
                element.find('a').on('click', function () {
                    var count = 0;
                    var Id = $(this).prop('id');
                    switch(Id) {
                        case 'first':
                            count = 1; //update to `homeController`
                            break;
                        case 'prev':
                            count -= 1;  //update to `homeController`
                            break;
                        case 'next':
                            count += 1;  //update to `homeController`
                            break;
                        case 'last':
                            count = scope.totalPages; //get from `homeController`
                            break;
                    }
                    scope.count = count;
                });
            }
        }
    })

【讨论】:

  • 我的观点没有更新......我猜这部分没有工作:'scope.$apply(function () { count = count; });'
【解决方案2】:

我将使用对象定义和范围映射,例如

$scope.page = {
    totalPages: 10,
    count: 4
};

然后

app.directive("docNavigation", function () {
    return {
        restrict: "E",
        replace: true,
        //use your url
        template: '<div>' + '<a data-type="first" href="">first</a>' + '<a data-type="prev" href="">prev</a>' + '<a data-type="next" href="">next</a>' + '<a data-type="last" href="">last</a>' + '</div>',
        scope: {
            page: '='
        },
        link: function (scope, element, attr, controller) {
            element.find('a').on('click', function () {
                //using hard coded ids in a directive is dangerous as there can be other elements with the same id
                var type = angular.element(this).attr('data-type');
                switch (type) {
                    case 'first':
                        scope.page.count = 1; //update to `homeController`
                        break;
                    case 'prev':
                        scope.page.count -= 1; //update to `homeController`
                        break;
                    case 'next':
                        scope.page.count += 1; //update to `homeController`
                        break;
                    case 'last':
                        scope.page.count = scope.page.totalPages; //get from `homeController`
                        break;
                }
                scope.$apply(function () {})
            })
        }
    }
});

演示:Fiddle

【讨论】:

  • 我这样申请,但不工作:scope.$apply(function () { this.page.count = count;});
  • 我仍然收到错误,因为“未捕获的 ReferenceError:未定义计数”
  • @3gwebtrain 你为什么要这样做.. 上面的代码没有它也能工作
  • 不,我按照您的建议进行了更新。仍然遇到上述问题。
  • 抱歉 Arun,我的错误,我没有正确更新您的 scope-page-count 分配正确。顺便说一句,为什么我们需要 'scope.$apply(function(){})`..?
【解决方案3】:

另一个答案中提供的解决方案是正确的,即您可以将变量传递给您的指令。

我想指出,尽管您将 vanilla 和 AngularJS 混为一谈。在您的指令中,您在 Angular 的意识之外附加了一个单击事件处理程序,这将在以后导致问题。因此,我建议将您的指令代码更新为:

app.directive("docNavigation", function () {
    return {
        restrict: "E",
        replace: true,
        templateUrl: '/views/directiveViews/docNavigation.html',
        scope: {
            page: '='
        },
        link: function (scope, element, attr, controller) {

            scope.goToPrevious = function(){
                 scope.page.count -= 1;
            };

            scope.goToNext = function(){
                scope.page.count += 1;
            };

            scope.goToFirst = function(){
                scope.page.count = 1;
            };

            scope.goToLast = function(){
                scope.page.count = scope.page.totalPages;
            }
        }
    }
});

然后将您的模板更新为

<nav class="navbar navbar-inverse">
    <ul class="nav navbar-nav">
        <li class="active"><a ng-click="goToFirst()" href="#">First</a></li>
        <li><a ng-click="goToPrevious()" href="#">Previous</a></li>
        <li><a ng-click="goToNext()" href="#">Next</a></li>
        <li><a ng-click="goToLast()" href="#">Last</a></li>
    </ul>
</nav>

【讨论】:

  • 是的,我同意,但我想用jQuery 比angular lite 玩得更好。
  • 但是link: function (scope, element, attr, controller) { 中的controller 是什么?我们也可以使用controller吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
  • 1970-01-01
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多