我一直试图解决这个问题几个小时,并试图在堆栈溢出和其他网站上找到一个有效的解决方案,但到目前为止还没有工作。
问题
我正在构建一个旅行网络应用程序,允许用户记录和查看他们的旅程(例如公路旅行)。目前,我正在实施一项功能,让用户可以在一个单独的视图中查看特定旅程,这些视图是他们从旅程列表中选择的。我传递所选旅程的ID并从MongoDB中检索一个对象。我用POST实现了这个。它的工作原理是所选行程的_id在请求中传递,然后用于通过Model.findById识别文档 - 然后响应产生数据。数据绑定到$ scope.selection。
但是$ scope.selection包含数据(当记录到控制台时),我似乎无法将其绑定到视图(称为view_journey)。这意味着,无论何时我想访问,例如我的view_journey.html中的selection.name,表达式或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 :(得分:0)
在摆弄代码之后,我可以确认在触发路径时,您将获得具有新的清洁范围的控制器的新实例。这是AngularJS的预期行为。
您可以通过添加一条简单的日志消息作为控制器的第一行来验证这一点:
console.log($scope.selected);
你会注意到它总是退出&#34; undefined&#34;因为变量从未设置过(在viewJourneyById中)。如果您保留登录并测试代码,您将在viewJourneyById中看到日志记录,但随后立即显示&#34; undefined&#34;因为它将view_journey.html模板加载到ng-view中并创建mainCtrl的新实例。 &#34; undefined&#34;的存在在新视图加载后显示在路径更改时再次执行控制器功能。
有几种方法可以解决这个问题。首先,您可以创建工厂或服务,将其注入控制器,并让它为您存储数据。这实际上是他们存在的原因之一,即在控制器之间共享数据。
<强>工厂:强>
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服务调用,即使您只是在同一个页面之间来回转换。