2016-02-11 48 views
0

我一直试图解决这个问题几个小时,并试图找到堆栈溢出和其他网站的工作解决方案,但目前为止还没有工作。无法将POST响应对象绑定到我的视图

的问题

我建立一个游记web应用程序,允许用户登录和查看他们的行程(例如一个客场之旅)。目前,我正在实施该功能,让用户可以在单独的视图中查看他们从旅程列表中选择的特定旅程。我传递选定旅程的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> 

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

+0

index.html和view_journey.html如何相关?它看起来像你有一个角路由发射,如果这样(通常)创建一个新的控制器实例与一个单独的范围,所以它可能是$ scope.selection真的是未定义的。尝试将view_journey.html放在与index.html相同的模板中,以测试您的数据流。或者,您必须提供有关应用程序结构的更多信息。 – tokkov

+0

是的,我在我的app.js文件中设置了一个路径,但是我只使用一个控制器(mainCtrl)作为整个应用程序(是的,我知道,我应该尽快更改)...所以我不认为这是问题。此外,以完全相同的方式设置的其他路线也可以访问相似的数据集。 下面是路由和mainCtrl的完整app.js文件: [app.js](https://github.com/supernoir/travelogue/blob/master/app/scripts/app.js) 这里是我的server.js [server.js](https://github.com/supernoir/travelogue/blob/master/app/server.js) –

+0

无论何时控制器连接到您的视图,都会创建一个控制器的新实例有自己的范围。即使您使用具有不同模板的相同控制器,每当路线发生火灾时也会发生这种情况。这意味着你的数据实际上并不存在于新控制器的范围内,除非你以某种方式将其放在那里。通常这是通过工厂或服务完成的。我会仔细看看你的代码,看看我能看到什么。 – tokkov

回答

0

摆弄你的代码后,我可以证实,当触发路线时,你将得到一个新的,干净的范围的控制器的新实例。这是AngularJS的预期行为。

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

console.log($scope.selected); 

你会发现,它总是登出“未定义”,因为该变量从未设置(内viewJourneyById )。如果您离开该登录并测试代码,您将在viewJourneyById中看到日志激发,但随后将view_journey.html模板加载到ng-view中并立即创建“未定义”,并创建mainCtrl的新实例。在新视图加载之后存在“未定义”,表明控制器功能正在对路线改变再次执行。

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

厂:

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> 

更多或少一些这样的事情。另一种方法是将旅程ID链接作为查询字符串的一部分,然后在控制器中检查是否存在旅程ID,如果找到,则查找旅程。这将是一个启动路由,加载控制器的新实例,然后在view_journey页面上加载数据的情况。您可以在这样控制器搜索查询字符串参数:

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

两种方法都可行。工厂/服务方法允许您通过存储一些数据来最大限度地减少Web服务调用。然而,那么你必须开始考虑数据管理,所以你的应用程序中没有陈旧的数据。查询字符串方式是解决问题的最快方法,但意味着即使您只是在相同的两页之间来回切换,每个路由转换都将等待Web服务调用。

+0

太棒了,这个作品!感谢一堆:) –

相关问题