1

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

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

HTML:

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

角度指令和路由:

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"
}

希望$scope.pathCtrl2 中的更改会更新面包屑指令,但它没有发生。我必须相信这与它们的相对范围有关,但根本无法很好地理解它以了解什么。我已经阅读了数十篇关于它的文章和 StackOverflow 帖子,但没有什么具体足以让我看到我缺少什么。

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

非常感谢!

新西兰

4

1 回答 1

5

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

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

现在您希望path在另一个控制器中更改此变量Ctrl2。我假设您正试图Ctrl2Ctrl1. 为此,首先检查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. Wrap the whole template so that it can be returned as a single HTML element.
  3. Specify the place where you want the contents of the to go. Notice the ng-transclude. That is the place where the contents go.

You will notice now that the content is getting replaced now. Except the path is not getting updated with the path value from the child controller. Have a look at this https://stackoverflow.com/a/14049482/1057639 answer. It is an amazing explanation of scope / prototypical inheritance. Basically, your write to path is creating a new path variable in the child scope that is overshadowing the parent path ( which is being used by the directive).

Your best bet in this scenario is to create an addPath function in the parent scope and use it ( in child scopes ) to add new Path when you define new subviews.

Here is a fiddle that does all these.

于 2012-12-28T16:49:14.800 回答