AngularJS - 带有 Rails 3.2.3 的 $http POST

Posted

技术标签:

【中文标题】AngularJS - 带有 Rails 3.2.3 的 $http POST【英文标题】:AngularJS - $http POST with Rails 3.2.3 【发布时间】:2012-05-20 10:30:05 【问题描述】:

我正在使用 AngularJS 1.0.0rc8 和 Crud 构建一个简单的联系人管理应用程序。

获取当前存在的联系人列表没有问题,但是在尝试将新联系人保存到服务器时,会创建一个新行 - 包含正确的 id、created_at 和 updated_at 值 - 但其余模型数据被忽略。

这是一个屏幕截图来说明我的意思:

如您所见,数字 4 和 5 被赋予了 ID,但 first_name、last_name 和 phone_num 并未保存到数据库中。

我在控制器中使用 $scope.addContact 函数来处理对象。

这是联系人列表控制器的完整代码:

'use strict';

function ContactListCtrl($scope, $http) 
  $http.get('/contacts').success(function(data) 
    $scope.contacts = data;
  );    

  $scope.addContact = function(data)       

    $http.post('/contacts/', data).success(function(data) 
        console.log(data);
        data.first_name = $("#new_contact_first_name").val();
        data.last_name = $("#new_contact_last_name").val();
    );

    this.newFirstName = '';
    this.newLastName = '';
  ;

;

在 new-contact.html 部分单击 'Save' 后,对象会记录到控制台,如果我检查其内容,那么肯定会收集值 - 请注意 Jimi Hendrix 是那里:

这是 new-contact.html 模板中显示的表单:

<form id="contact_form" ng-submit="addContact()">
            <input type="text" id="new_contact_first_name" name="newContactFirstName" ng-model="newFirstName" placeholder="First Name"></br>
            <input type="text" id="new_contact_last_name" name="newContactLastName" ng-model="newLastName" placeholder="Last Name"></br>
            <input type="button" id="contact_submit_btn" value="Add Contact" class="btn btn-primary">               
        </form>

addContact() 函数在使用 JQuery 提交表单后触发:

$(document).ready(function()       

        $("#contact_submit_btn").click(function()          
            $("#contact_form").submit();
        );
    );

(有些东西告诉我,我可能没有正确使用 ng-model 属性。)

关于我在哪里出错的任何想法?或者关于如何更好地实施此设计的想法?

谢谢。


以下更新:

这是我更新后的完整控制器代码 - 在 Sathish 的帮助下:

 // contacts controllers

'use strict';

function ContactListCtrl($scope, $http, Contacts)    

  $scope.contacts = Contacts.index();  

  $scope.addContact = function() 
        var newContact = 
            first_name: $scope.newContactFirstName,
            last_name: $scope.newContactLastName
        ;

        var nc = new Contacts( contact: newContact );

        nc.$create(function() 
            $scope.contacts.push(nc);
            // now that the contact is saved, clear the form data
            $scope.newContactFirstName = "";
            $scope.newContactLastName = "";
            )
        

;

ContactListCtrl.$inject = ['$scope', '$http', 'Contacts'];


function ContactDetailCtrl($scope, $routeParams, Contacts)   
    $scope.contact = Contacts.get( contact_id: $routeParams.contact_id ); 


ContactDetailCtrl.$inject = ['$scope', '$routeParams', 'Contacts'];

我现在收到错误消息:未知的联系人提供程序。这是错误的截图

好的,我设法通过向主 App 文件提供 ngResource 来修复该错误。这是它的样子:

// main app javascript file

'use strict';

angular.module('contactapp', ['ngResource']).
  config(['$routeProvider', function($routeProvider) 
  $routeProvider.
      when('/contacts', template: 'assets/app/partials/contact-list.html',   controller: ContactListCtrl).
      when('/contacts/new', template: 'assets/app/partials/new-contact.html',   controller: ContactListCtrl).
      when('/contacts/:contact_id', template: 'assets/app/partials/contact-detail.html', controller: ContactDetailCtrl).
      otherwise(redirectTo: '/contacts');
]);

我收到一个新错误:警告:无法验证 CSRF 令牌的真实性

好的,通过向 API 控制器添加回调也设法解决了这个问题: Rails shows "WARNING: Can't verify CSRF token authenticity" from a RestKit POST

现在我回到原来的问题。调用 create 方法时,会在数据库中保存一个新行,但模型数据不会。

太棒了……终于搞定了。

问题出在 $scope.addContact 函数上。它使用输入的“名称”而不是位于模板中的名为“newFirstName”和“newLastName”的 ng-model 绑定。

更新后的函数如下所示:

$scope.addContact = function() 
        var newContact = 
            first_name: $scope.newFirstName,
            last_name: $scope.newLastName
        ;

        var nc = new Contacts( contact: newContact );

        nc.$create(function() 
            $scope.contacts.push(nc);
            // now that the contact is saved, clear the form data
            $scope.newFirstName = "";
            $scope.newLastName = "";
            )
        

【问题讨论】:

【参考方案1】:

使用联系人服务可以更好地实现这一点。请在 app/assets/javascripts/services.js.erb 中定义一个 Contacts 服务,如下所示:

var servicesModule = angular.module('<your app name>',
  [<list of modules needed by this app>]);

servicesModule.factory('Contacts', function($resource) 
  var ContactsService = $resource('/contacts/:contact_id', , 
    'create':  method: 'POST' ,
    'index':  method: 'GET', isArray: true ,
    'update':  method: 'PUT' ,
    'destroy':  method: 'DELETE' 
  );
  return ContactsService;
);

改变控制器中的addContact方法如下图:

  function ContactListCtrl($scope, $http, Contacts) 
    ...
    ...
    ...
    $scope.addContact = function () 
      var newContact = 
        first_name: $scope.newContactFirstName,
        last_name: $scope.newContactLastName
      ;

      var nc = new Contacts( contact: newContact );
      nc.$create(function() 
        $scope.contacts.push(nc);
        // now that the contact is saved, clear the form data.
        $scope.newContactFirstName = "";
        $scope.newContactLastName = "";
      );
    ;
    ...
    ...
    ...
  
  ContactListCtrl.$inject = ['$scope', '$http', 'Contacts'];

除此之外,您还可以简化$http.get(...) 部分。你可以使用Contacts.index();

注意:

如果您提供了ng-app="MyAppName",请将&lt;your app name&gt; 替换为MyAppName&lt;list of modules needed by this app&gt; 需要替换为以逗号分隔的字符串列表,表示您的应用程序所需的任何模块。

【讨论】:

不应该把Contacts注入控制器吗? @DominicMitchell,是的。懒得提了。将编辑答案以将联系人注入控制器。感谢您指出。 @Sathish - 非常感谢您的帮助。我实现了您的代码,并且收到联系人的“未知提供者”错误。我在原始帖子的底部创建了一个更新部分,其中包含更多详细信息。 @Sathish - 划掉最后一条评论。现在一切都很好,感谢您对服务的帮助。【参考方案2】:

检查您模型上的attr_accessible。有了新的 3.2.3 rails,所有模型属性都默认受到保护,不会被批量分配。

【讨论】:

感谢马克的反馈。不过,我认为这不是问题所在,因为我的所有模型属性都列在 attr_accessible 帮助器之后。

以上是关于AngularJS - 带有 Rails 3.2.3 的 $http POST的主要内容,如果未能解决你的问题,请参考以下文章

带有折线的文本在 Rails 中不起作用

rails + angularjs 在编辑时将值加载到文本字段中

预编译 Rails AngularJS 资产

如何在 Rails 4 中为 AngularJS 更正设置根路由?

rails-api 和 angularJs 中的 CORS

隧道 AngularJs 请求在外部 API 中使用 Rails