无法将来自 POST 的响应对象绑定到我的视图

Cannot bind response object from POST to my view

几个小时以来,我一直在努力解决这个问题,并试图在堆栈溢出和其他网站上找到可行的解决方案,但 none 到目前为止一直有效。

问题

我正在构建一个游记网络应用程序,允许用户记录和查看他们的旅程(例如公路旅行)。目前,我正在实施一项功能,让用户可以在他们从旅程列表中选择的单独视图中查看特定旅程。我传递了所选旅程的 ID,并从 MongoDB 中检索了一个对象。我使用 POST 实现了这个。它的工作原理是所选旅程的 _id 在请求中传递,然后用于识别带有 Model.findById 的文档 - 然后响应产生数据。数据绑定到 $scope.selection.

但是虽然 $scope.selection 包含数据(当记录到控制台时),但我似乎无法将它绑定到视图(称为 view_journey)。意思是,每当我想访问时,例如selection.name 在我的 view_journey.html 中,表达式或 ng-bind 留空。

app.js

$scope.viewJourneybyId = function(id) {
    var selectOne = { _id : id };
    $http.post('http://localhost:8080/view_journey', selectOne).
    success(function(data) {
        $scope.selection = data;
        $scope.$apply();
        console.log("POST found the right Journey");
        console.log($scope.selection);
    }).error(function(data) {
        console.error("POST encountered an error");
    })    
}  

server.js

app.post("/view_journey", function(request, response, next) {
   Journeys.findById(request.body._id, function(error, selection) {
      if (error)
         response.send(error)
      response.json({ message: 'Journey found!', selection });
      });
   });

index.html

<tr ng-repeat="journey in journeys">
   <td>
      <a href="#/view_journey" ng-click="viewJourneybyId(journey._id)">
      {{journey.name}}</a>
   </td>
   <td>...</td>     
</tr>

view_journey.html

<div class="panel panel-default">
   <div class="panel-heading">
     <h2 ng-bind="selection.name"></h2>
     <!-- For Debugging -->
     ID <span ng-bind="selection._id">
   </div>
   <div class="panel-body">
     <table class=table>
        <caption>{{selection.desc}}</caption>
        ...
     </table>
   </div>
</div>

意见反馈 这是我关于堆栈溢出的第一个问题,所以也请告诉我我是否以可能被误解的方式表达了我的问题,以及我是否应该提供更多细节,例如控制台输出。谢谢 ;)

在修改了您的代码后,我可以确认在触发路由时您将获得一个新的控制器实例,该实例具有一个新的、干净的范围。这是 AngularJS.

的预期行为

您可以通过在控制器的第一行添加一条简单的日志消息来验证这一点:

console.log($scope.selected);

您会注意到它总是注销 "undefined" 因为从未设置变量(在 viewJourneyById 中)。如果您保留登录并测试代码,您将在 viewJourneyById 中看到日志记录,但随后 "undefined" 立即将 view_journey.html 模板加载到 ng-view 并创建 mainCtrl 的新实例。新视图加载后 "undefined" 的存在表明控制器功能正在路由更改上再次执行。

有几种方法可以解决这个问题。首先,您可以创建一个工厂或服务,将其注入您的控制器,并让它为您存储数据。这实际上是它们存在的原因之一,即在控制器之间共享数据。

工厂:

travelogueApp.factory('myFactory',function() {
    return {
        selected: null,
        journeys: []
    };
});

控制器:

travelogueApp.controller('mainCtrl', ['$scope','$http','$location','myFactory', function ($scope, $http, $location, myFactory) {
    // put it into the scope so the template can see it.
    $scope.factory = myFactory; 

    // do other stuff

    $scope.viewJourneybyId = function(id) {
        var selectOne = { _id : id };
        $http.post('http://localhost:8080/view_journey', selectOne)
            .success(function(data) {
                $scope.factory.selection = data;
                console.log("POST found the right Journey");
                console.log($scope.factory.selection);
            })
            .error(function(data) {
                console.error("POST encountered an error");
            })    
        }  
    }]); // end controller

模板:

<div class="panel panel-default">
    <div class="panel-heading">
        <h2>{{factory.selection.name}}</h2>
    </div>
    <div class="panel-body">
        <table class=table>
        <caption>{{factory.selection.desc}}</caption>
        ...
        </table>
    </div>
</div>

或多或少是这样的。另一种方法是构建 link 并将旅程 ID 作为查询字符串的一部分,然后在控制器中检查旅程 ID 是否存在,如果找到,则查找旅程。这将是触发路由、加载控制器的新实例然后在进入 view_journey 页面后加载数据的情况。您可以像这样在控制器中搜索查询字符串参数:

var journey_id = $location.search().id;

两种方法都行。 factory/service 方法允许您通过存储一些数据来最大程度地减少随时间推移的 Web 服务调用。但是,您必须开始考虑数据管理,这样您的应用程序中就不会出现陈旧数据。查询字符串方式将是解决问题的最快方式,但这意味着每个路由转换都将等待 Web 服务调用,即使您只是在相同的两个页面之间来回移动。