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

nat*_*rek 1 scope angularjs

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

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

HTML:

<breadcrumb></breadcrumb>
<div ng-view></div>
Run Code Online (Sandbox Code Playgroud)

角度指令和路由:

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
            });
    }]);
Run Code Online (Sandbox Code Playgroud)

控制器

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"
}
Run Code Online (Sandbox Code Playgroud)

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

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

非常感谢!

新西兰

gan*_*raj 5

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

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

现在您希望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>
Run Code Online (Sandbox Code Playgroud)

如果我们对您的代码进行此更改,它仍然无法正常工作.这是因为当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
            }
    })
Run Code Online (Sandbox Code Playgroud)

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

  1. 添加了一个名为transclude的属性到指令对象并将其设置为true.
  2. 包装整个模板,以便它可以作为单个HTML元素返回.
  3. 指定您想要的内容的位置.注意ng-transclude.那是内容的去处.

您现在会注意到内容现在已被替换.除了路径没有使用子控制器的路径值更新.看看这个/sf/answers/983463771/答案.这是对范围/原型继承的惊人解释.基本上,您对路径的写入是在子范围中创建一个新的路径变量,该路径变量掩盖了父路径(指令正在使用该路径).

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

这是一个完成所有这些的小提琴.