如何使用来自子控制器内的父控制器的多个异步HTTP请求的结果?结果在视图内部解析,但不在另一个控制器中解析。下面的代码片段是我尝试使用文字coffeescript生成一个简洁的例子。
我意识到能够重现这一点有点困难,因为需要运行CouchDB并为其添加带有设计文档的数据库,但我希望你可以不遵循这个例子。
我已尝试在代码段中包含所有相关注释,因此请为其长度道歉。
<html ng-controller="parentCtrl">
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/coffee-script/1.7.1/coffee-script.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-resource.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-route.min.js"></script>
</head>
<body>
<nav>
<ul>
<li ng-repeat="db in dbs">
{{db.name}}
<ul>
<li ng-repeat="foo in db.foos">
<a ng-href="#/{{db.id}}/foos/{{foo._id}}">{{foo.name}}</a>
</li>
</ul>
</li>
</ul>
</nav>
<ng-view></ng-view>
<script type="text/ng-template" id="foo">
<h1>{{foo.name}}</h1>
</script>
<script type="text/literate-coffeescript">
app = angular.module 'test', ['ngResource', 'ngRoute']
ngResource definition for CouchDB documents; the urls are relative because this
very document gets served from inside of the main application database design
document as an attachment.
app.factory 'Doc', ['$resource', ($resource) ->
$resource '/:db/:doc', { doc: '@_id', rev: '@_rev' },
There will be many CouchDB databases, each containing documents which have a
`type` with value `foo`. Then to list all `foo`s, there is a view called `foos`
in each of the databases whose definition is: `emit(doc._id, doc) if doc.type
is 'foo'`. The following additional method is for using that view.
query:
method: 'GET', url: '/:db/_design/ddoc/_view/:view', isArray: true,
transformResponse: (response) ->
angular.fromJson(response).rows.map (row) -> row.value
]
This parent controllers data needs to be available for the child controller(s).
app.controller 'parentCtrl', ($scope, Doc) ->
$scope.dbs = []
Doc.get db: 'appdb', doc: '_design/app_ddoc', (app_ddoc) ->
The main application design document contains a key `db_ids` whose value is an
array of database ids (e.g. `['c-12345', 'c-54321', ...]`). The actual names of
those databases are contained inside their design document, which then needs
to be fetched separately.
angular.forEach app_ddoc.db_ids, (db_id) ->
Doc.get db: db_id, doc: '_design/ddoc', (ddoc) ->
Doc.query db: db_id, view: 'foos', (foos) ->
$scope.dbs.push id: db_id, name: ddoc.name, foos: foos
app.controller 'childCtrl', ($scope, $routeParams, Doc) ->
To display information of the currently selected `foo`, there shouldn't be any
reason to re-fetch its data from the server since that has already been done
in the `parentCtrl`. Ideally, filter it out from the `$scope.dbs`.
$scope.foo = $scope.dbs.filter((db) -> db.id is $routeParams.db).pop()
.foos.filter (foo) -> foo.id is $routeParams.doc
Alas, `$scope.dbs` hasn't resolved yet, presumably, and because of that, an
error is displayed: `Error: 'undefined' is not an object (evaluating
'$scope.dbs.filter')`.
app.config ['$routeProvider', ($routeProvider) ->
$routeProvider.when '/:db/foos/:doc',
templateUrl: 'foo'
controller: childCtrl
]
angular.element(document).ready -> angular.bootstrap document, ['test']
</script>
</body>
</html>
&#13;