如何在使用$ route和partials时更新AngularJS指令

时间:2012-12-28 14:13:23

标签: scope angularjs

http://jsfiddle.net/MTzJF/36/

上面的JSFiddle是为解释这个问题而设立的。但是,基本上:

HTML:

<breadcrumb></breadcrumb>
<div ng-view></div>

Angular Directive&amp;路由:

angular
    .module('app', [])
    .directive('breadcrumb', function() {
        return {
            restrict: 'E',
            template: "<ul class='breadcrumb'><li ng-repeat='node in path'><a ng-href='{{node.url}}'>{{node.label}}</a></li></ul>",
            replace: true,
            controller: Ctrl1
        }
    })
    .config(['$routeProvider', function($routeProvider) {
        $routeProvider
            .when('/', { 
                template: '<h1>{{pgTitle}}</h1>', 
                controller: Ctrl2
            });
    }]);

控制器

function Ctrl1($scope) {
    $scope.path = [{
            label: 'Home',
            url: '#/'}];
    $scope.pgTitle = "Home"       
}
function Ctrl2($scope, $routeParams) {
    $scope.path = [{
            label: 'Home',
            url: '#/'},{
            label: 'Node 2',
            url: '#/node2'}];
    $scope.pgTitle = "Node 2"
}

期待在Ctrl2中更改$scope.path将更新breadcrumb指令,但它没有发生。我不得不相信它与它们的相对范围有关,但根本不能理解它看得怎么样。我已经阅读了很多文章和StackOverflow帖子,但没有什么特别的东西可以让我看到我错过的内容。

我希望有人能指出我正确的方向。

非常感谢!

nz的

1 个答案:

答案 0 :(得分:5)

你的小提琴不工作的原因是因为(正如你正确识别的)范围问题。您的Ctrl1是控制器,用于控制指令的范围。该指令正在寻找一个名为path的变量,它是一个路径数组。如果我们看一下该范围内的路径变量,它似乎只包含1个值。

function Ctrl1($scope) {
    $scope.path = [{
            label: 'Home',
            url: '#/'}];
    $scope.pgTitle = "Home"       
}

现在您希望在另一个控制器path中更改此变量Ctrl2。我假设您试图让Ctrl2“的范围继承Ctrl1的范围。要实现此目的,请首先检查定义了哪个元素Ctrl2。该元素(html元素)是Ctrl1元素的子元素吗?

来自您的HTML:

Ctrl1的元素:<breadcrumb></breadcrumb>

Ctrl2的元素:<div ng-view></div>

要让Ctrl2成为Ctrl1的孩子:您的HTML结构应如下所示:

<breadcrumb>
    <div ng-view></div>
</breadcrumb>

如果我们对您的代码进行此更改,它仍然无法正常工作。这是因为当angular查看<breadcrumb>的指令时,它不知道它应该对该节点内部的东西做什么。 <breadcrumb>是一个html节点。由于它是一个节点,因此它可以包含其中的内容/其他节点。当您使用模板替换此痕迹导航节点时,您还应该给出效果的角度指示:“如果您发现我的内容,请将其放在此处”。这就是你如何做到的。

将指令代码修改为:

.directive('breadcrumb', function() {
            return {
                restrict: 'E',
                template: "<div><ul class='breadcrumb'><li ng-repeat='node in path'><a ng-href='{{node.url}}'>{{node.label}}</a></li></ul><div ng-transclude></div></div>",
                replace: true,
                transclude : true,
                controller: Ctrl1
            }
    })

这里几乎没有差异/变化。

  1. 在指令对象中添加了一个名为 transclude 的属性,并将其设置为 true
  2. 包装整个模板,以便可以将其作为单个HTML元素返回。
  3. 指定您要去的内容的位置。注意ng-transclude。这就是内容的去处。
  4. 现在您将注意到内容现在已被替换。除了路径没有使用子控制器的路径值更新。看看这个https://stackoverflow.com/a/14049482/1057639答案。这是对范围/原型继承的惊人解释。基本上,您对路径的写入是在子范围中创建一个新的路径变量,该路径变量掩盖了父路径(指令正在使用该路径)。

    在这种情况下,最好的办法是在父作用域中创建一个addPath函数,并在定义新的子视图时使用它(在子作用域中)添加新的Path。

    这是完成所有这些工作的fiddle