2013-10-24 32 views
0

我有一个页面,其中包含一个可以更改服务器上资源状态的按钮。一切都连接起来,工作正常。但我不得不求助于发送浏览器“回来”的服务器响应,因为我不想为动作url显示新模板。AngularJS + Rails:获取资源,但留在当前页面

这似乎是一个典型的事情:请服务器做一些事情,然后获取资源的当前状态,并在当前模板中重新显示它而不重新提取模板。

页面上的标记是这样的:

<a ng-href="/api/preference/{{video._id}}/add_to_watchlist" data-method="get"> 
    <i rel="tooltip" data-original-title="Add to watchlist" class="icon-3x action-icon 
     icon-plus-sign" ng-class="{iconSelected : video.user_watchlist == 1}"> 
    </i> 
</a> 

取决于$ scope.video.watchlist的价值这凸显的图标。点击后,它会触发服务器上的自定义操作,将正在查看的视频添加到当前用户的监视列表中。创建的网址是/api/preference/{{video._id}}/add_to_watchlist,这会触发服务器控制器,它可以正确执行操作,但不会转到/api/preference/{{video._id的模板}}/add_to_watchlist服务器通过告诉客户端在Rails中“返回”来响应,这是redirect_to :back

显然这是错误的。它的工作原理,但重新提交整个页面标记和数据。

加载原始数据的AngularJS控制器是在这里:

GuideControllers.controller('VideoDetailCtrl', ['$scope', 'Video', 
    function($scope, Video) { 
     var pattern = new RegExp(".*/([0-9,a-f]*)", "gi"); 
     //ugh, there must be a better way to get the id! 
     $scope.video = Video.get({ id: pattern.exec(document.URL)[1] }); 
    } 
]); 

这里是得到JSON

var VideoServices = angular.module('VideoServices', ['ngResource']); 

VideoServices.factory('Video', ['$resource', 
    function($resource){ 
     return $resource("/api/videos/:id", {id: "@id"}, { 
      update: {method: "PUT"}, 
      query: { 
       isArray: true, 
       method: "GET", 
       headers: { 
        "Accept": "application/json", 
        "X-Requested-With": "XMLHttpRequest" 
       } 
      }, 
      get: { 
       isArray: false, 
       method: "GET", 
       headers: { 
        "Accept": "application/json", 
        "X-Requested-With": "XMLHttpRequest" 
       } 
      } 
     }); 
    } 
]); 

不知怎的,我需要

  1. 告诉服务器资源add_to_watchlist而不更改浏览器的URL
  2. 在不重新加载模板的情况下触发视频json的重新获取。

回答

1

看起来你似乎依靠路由来处理服务器上的模型更新,而不是通过角度的$资源服务来完成。这里有一个快速和肮脏的:

相反的路由,调用一个函数,当用户点击:

<a ng-click="addToWatchlist(video._id)"> 
<i rel="tooltip" data-original-title="Add to watchlist" class="icon-3x action-icon 
    icon-plus-sign" ng-class="{iconSelected : video.user_watchlist == 1}"> 
</i> 
</a> 

添加点击处理函数到控制器(我使用$ HTTP这里,但你会最好将自定义操作添加到视频资源中)。在成功回调中,您可以重新加载视频。或者,更好的是,您可以从add_to_watchlist操作返回视频。

检查出http://docs.angularjs.org/tutorial/step_07它解释$ routeParams(回答您的评论关于获取视频ID)。

GuideControllers.controller('VideoDetailCtrl', ['$scope', '$http', '$routeParams', 'Video', 
    function($scope, $http, $routeParams, Video) { 
     $scope.video = Video.get({ id: $routeParams.videoId }); 
     $scope.addToWatchlist = function(videoId) { 
      $http.get('/api/preference/'+videoId+'/add_to_watchlist').success(function() { 
       $scope.video = Video.get({ id: $routeParams.videoId }); 
      }; 
     }; 


    } 
]); 
+0

这说明了很多。然而,如我所料,来自$ http.get的响应是200,并且没有调用成功函数来刷新模型。 – pferrel

+0

我刚刚测试了一个空的200响应$ http.get(...),并调用了成功函数。你确定这是问题吗? – redmallard

+0

糟糕,405,我固定。对于后人,我从你的回答中了解到,$ routeParams是一个用routeProvider中指定的路由的每个部分填充的对象。此外,将一个函数附加到一个点击看起来首先在该函数名称的作用域中。资源或$ http.get或其他动词返回一个承诺。要查看返回的数据或触发下一个http操作,需要附加get(或其他动词)的“.success”方法的函数。你的例子展示了如何使用所有这些。 – pferrel