在子控制器中使用来自父控制器的多个HTTP请求结果

时间:2014-09-21 10:06:24

标签: angularjs coffeescript couchdb

如何使用来自子控制器内的父控制器的多个异步HTTP请求的结果?结果在视图内部解析,但不在另一个控制器中解析。下面的代码片段是我尝试使用文字生成一个简洁的例子。

我意识到能够重现这一点有点困难,因为需要运行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;
&#13;
&#13;

0 个答案:

没有答案