【发布时间】:2014-03-15 05:57:59
【问题描述】:
如果我将 ui-view 嵌套在 transclude=true 的指令中,则不会加载视图内容。没有干预指令,它可以正常工作。
所以页面包含:
<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中,但是这似乎不是实际可见的样本指令节点,而是它的克隆。我猜它与编译顺序有关,因此我需要在指令中做一些聪明的事情,但我在 angular api 帮助中找不到任何涵盖这一点的内容。
我尝试添加一个后链接函数并从那里调用 $transclude,但没有任何区别。
任何人都可以建议我需要在指令中添加什么,这样就可以了。 谢谢
更新 进一步调查的新信息: 原因似乎是这个(此时不是解决方案,但我可以看到它为什么会发生)。 在 Angular 的函数 applyDirectivesToNode(angular.js 第 5919 行)中,如果指令指定 transclude=true,则克隆原始指令节点以制作模板节点。即模板不是在dom中可见的原始节点。现在,当调用 angular-ui-router.js 第 2204 行中 ui-view 的 compile 函数时,它会抓取 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>
【问题讨论】:
-
查看this post on a similar issue,这也可能适用于您的情况。您可能只需要调用
$route的reload()。 -
谢谢,但是 $route 来自旧的角度路由 ngRoute 模块。我正在使用不同的 ui.router。话虽如此,在这种情况下,同样的原则可能会起作用,尽管我讨厌两次加载视图的想法 - 效率不高!无论如何,我会看看这种方法是否有效
-
ui.router 工作与
$route实现无关——它是一个单独的模块。即使在 1.2 上发生了重大更改,您对 ui.router 的使用应该没有什么区别(即重新加载应该可以工作)。无论如何,我建议的是在采取某种方法时解决问题的方法,如果您使用的是 ui.router,则可以完全避免这种方法。
标签: javascript angularjs angular-ui-router