嵌套在指令中的angular-ui视图不加载视图内容

时间:2014-02-15 21:06:47

标签: javascript angularjs angular-ui-router

如果我在带有transclude = true的指令中嵌入ui-view,则视图内容不会加载。没有干预指令,它工作正常。

所以页面包含:

<body>
<div ng-controller="MainController">
        <div ui-view="sampleView"></div>
</div>
</body>

出现sampleView内容。

但是,如果我把

<body>
<div ng-controller="MainController">
    <div sample-directive>
        <div ui-view="sampleView"></div>
    </div>
</div>
</body>

然后视图内容不会出现。

我创建了一个简单的html页面来演示这个问题,见下文。

据我所知,角度编译过程在angular-ui中的ui-view指令中正确调用了updateView,并且构建了视图内容并将其插入到sample-directive节点下的dom中,但是这似乎不是实际可见的样本指令节点,而是它的一个克隆。我猜这与编译的顺序有关,因此我需要在指令中做一些聪明的事情,但我无法在角度api帮助中找到任何能够涵盖这一点的内容。

我尝试添加一个post-link函数并从那里调用$ transclude但它没有任何区别。

任何人都可以建议我需要添加到指令中,这样就行了。 感谢

UPDATE 进一步调查的新信息: 似乎原因是这个(不是在这一点上解决方案,但我可以看到它为什么会发生)。 在angular的函数applyDirectivesToNode(angular.js第5919行)中,如果指令指定transclude = true,则克隆原始指令节点以生成模板节点。即模板不是dom中可见的原始节点。现在,当调用angular-ui-router.js第2204行中的ui-view的编译函数时,它会抓取ui-view节点的父节点的副本,并将其存储在parentEl中。但是,这就是问题发生的地方 - 这个父节点是ui-view节点的dom中的父节点。它肯定不是在链接后实际上在dom中结束的父实例。稍后当ui-view更新初始路由更改时,它会构建视图内容并将其插入parentEl(angular-ui-router.js第2273行)下,但正如我们之前看到的那样,链接后不在可见dom中。它是源html节点,而不是通过编译和链接ui-view嵌套的指令创建的克隆。

我认为这可能是ui-view中的错误。

可能有一种方法可以向指令添加变通方法,以获取后链接视图实例并将其放入指令中。如果我搞清楚,我会添加一个答案。

html演示如下问题:

<!DOCTYPE html>
<html lang="en" ng-app="viewInDirectiveApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>View inside a directive</title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js"></script>

<script src="modules/angular-ui-router.js"></script>

<script>
    var viewInDirectiveApp = angular.module('viewInDirectiveApp', ['ui.router']);

    viewInDirectiveApp.config(function ($stateProvider, $urlRouterProvider) {
        $stateProvider
            .state('sampleState', {
                url: '/sampleState',
                views: {
                    sampleView: {
                        template: 'This is the view content',
                        controller: function ($scope) {
                        }
                    }
                }
            });
        $urlRouterProvider.otherwise("/sampleState");
    })
    .controller('MainController', ['$scope',
        function ($scope) {
        }])
    .directive('sampleDirective', function () {
        return {
            template: 'Start directive content <div ng-transclude></div> End directive content',
            transclude: true
        };
    });
</script>
</head>
<body>
<div ng-controller="MainController">
    Before sampleDirective
    <div sample-directive>
        Before sampleView
        <div ui-view="sampleView"></div>
        After sampleView
    </div>
    After sampleDirective
</div>
</body>
</html>

2 个答案:

答案 0 :(得分:4)

答案 1 :(得分:0)

非常感谢掠夺者:http://plnkr.co/edit/TZ8hvkSbCIa0dTj0NkcG?p=preview - 似乎在Angular-routing中工作:http://dotjem.github.io/angular-routing/