假设我的AngularJS应用程序中有2个页面,一个显示有关作者的信息,另一个显示有关书籍的信息。我有一个单独的模板文件,控制器和路由。在作者页面上,我想显示他写的最新书的信息。我该怎么做?
我的每个路由都嵌入了一个URL参数,该参数告诉控制器哪个作者或书籍获取数据:
.when('/authors/:authorId', { templateUrl: 'author.html', controller: 'AuthorsController')
.when('/books/:bookId', { templateUrl: 'book.html', controller: 'BooksController')
据我了解,我不能使用ng-include
,因为它不支持路由参数,只支持模板文件。我可以使用带有src="/books/<bookId>"
的 IFrame ,但感觉应该有一个 Angular 方法来使用URL参数进行客户端包含。我阅读了ui-router
的{{3}}维基页面,但这仅涵盖了网址请求的接收结尾。
ng-view
似乎也不是正确的解决方案,因为我已经在index.html
格式模板中使用它了。这是我想要显示的HTML的逻辑结构:
<html ng-app="myApp">
<body>
<!-- displays template from the current route, e.g. /authors/1 -->
<div data-ng-view>
<!-- this HTML is loaded from the author.html template -->
Author: George R. R. Martin
(other author details...)
Most recent book:
*** THIS IS MY PROBLEM -- HOW TO INCLUDE /books/1 ? ***
<!-- this HTML is loaded from the book.html template -->
Title: A Dance with Dragons
Pub. date: 2011
...
</div>
</body>
</html>
澄清一些事情:
$scope
的服务器的数据,如{{ book.title }}
。$scope.latestBookId
包含我要显示的图书的ID。问题是如何将此ID用于ng-include
我的book.html
模板。这是我正在尝试做的事情:
app.controller('AuthorsController', function($scope) {
var authorId = $routeParams.authorId;
// these values would be retrieved from the server, using authorId:
$scope.author = ...;
$scope.allBooks = [1, 2, ..., 123];
$scope.mostRecentBookId = 123;
});
来自author.html
的片段:
Author: {{author.name}}
Most recent book:
<!-- all I'm trying to do is to include HTML from a route, but ng-include doesn't support using routes :( -->
<div ng-include='/books/{{mostRecentBookId}}'></div>
All books:
<!-- this is where @Akeem's solution breaks down; the knowledge of which bookId to include comes from the HTML below, not the AuthorsController -->
<div ng-repeat="bookId in allBooks">
<div ng-include='/books/{{bookId}}'></div>
<br/>
</div>
修改 我已将@ Akeem建议的解决方案应用于我的示例,并添加了有关它为何对我无效的评论:URL Routing
答案 0 :(得分:0)
根据我的理解,虽然ng-include创建了一个新范围,但它也从其父范围继承变量。因此,您可以在AuthorsController中设置$scope.bookId
并在BooksController中检查此变量。
app.controller('AuthorsController', function($scope) {
$scope.bookId = 123;
});
app.controller('BooksController', function($scope,$routeParams) {
if(!$scope.bookId){
$scope.bookId= $routeParams['bookId'];
}
var books = {'1' : 'To Killing a Mockingbird', '23' : 'Harry Potter', '123':'Catch 22'};
$scope.title = books[$scope.bookId];
});
从那里,您可以将ng-include指令与ng-controller指令结合使用,以在author.html模板中使用BooksController
<div ng-include src='"books.html"' ng-controller='BooksController'></div>
最后,在books.html中,您将所有变量引用为正常
<h1>{{title}}</h1>
<p>This is a book with an id of {{bookId}}</p>
<hr>
答案 1 :(得分:0)
好的,我从@ Akeem的解决方案ng-init
中找出了丢失的部分。我已将plnkr更新为使用此功能,并且可以正常使用。以下是如何包含另一个模板,使用ng-init设置$scope.bookId
变量来代替使用路由参数:
<div ng-init="bookId = author.mostRecentBook" ng-include="'book.html'"></div>
以下内容相同,但使用ng-repeat
创建新的$scope.bookId
变量:
<li ng-repeat="bookId in author.allBooks" ng-include="'book.html'"/>
这样做的缺点是调用代码更紧密地耦合到它所包含的模板文件,而不是使用路由URL作为抽象层。并且被调用的控制器需要检查范围和路由参数,以查看用于传递bookId
:
.controller('BooksController', function($scope, $routeParams) {
if (!$scope.bookId) {
$scope.bookId = $routeParams['bookId'];
}
...
})
我的偏好是找到一种方法,通过我设置的路线("/books/:bookId"
)来包含图书数据,但由于似乎没有办法做到这一点, ng-repeat
和ng-init
必须这样做。
深思熟虑:也许有角度的路线并不打算用于包含单个部分,并且每页只包含一个ng-view
模板。但是......我打赌你可以创建一个像:
<div ng-include-url="/books/1"></div>
在$route
服务中查找网址,并使用路由的templateUrl
(和controller
)属性进行ng-include。在将bookId
对象传递给控制器之前,它还必须从$routeParams
对象中的URL设置{{1}}。我既没有时间也没有使用AngularJS来实现这一目标,但是使用路径我已经配置来动态加载从一个模板/控制器到另一个模板/控制器的内容似乎很有用。