如何将Angular表单保存到rails后端的ruby上?

时间:2021-10-19 07:22:07

I'm new to Angular. I've tried everything I know how and Google searches have surprisingly few tutorials on this particular question. Here's the last code I tried:

我是Angular的新手。我已经尝试了我所知道的一切,谷歌搜索在这个特定问题上的教程很少。这是我尝试的最后一个代码:

index.html

<form ng-submit="addArticle(articles)">
<input type="text" id="title" ng-model="newPost.title">
<input type="text" id="body" ng-model="newPost.body">
<input type="submit" value="Submit">
</form>

articles controller

app.controller('ArticlesCtrl', function($scope, Article) {
  $scope.articles   = Article.query();
  $scope.newPost     = Article.save();
});

articles service (rails backend)

文章服务(rails后端)

app.factory('Article', function($resource) {
  return $resource('http://localhost:3000/articles');
});

I can retrieve data just fine. But I can't submit any new data to the rails backend. On page load, the rails server error is:

我可以很好地检索数据。但是我无法向rails后端提交任何新数据。在页面加载时,rails服务器错误是:

Started POST "/articles" for 127.0.0.1 at 2015-02-08 18:26:29 -0800
Processing by ArticlesController#create as HTML
Completed 400 Bad Request in 0ms

ActionController::ParameterMissing (param is missing or the value is empty: article):
  app/controllers/articles_controller.rb:57:in `article_params'
  app/controllers/articles_controller.rb:21:in `create'

Pressing the submit button does nothing at all. The form basically does not work and the page is looking for a submission as soon as it loads.

按提交按钮什么都不做。表单基本上不起作用,页面一加载就会查找提交。

I understand what the error says, that it's not receiving the parameters from the form. What I don't understand is what that should look like in my controller and/or form.

我理解错误说的是,它没有从表单中接收参数。我不明白的是我的控制器和/或表格应该是什么样的。

What am I doing wrong and how do I fix this?

我做错了什么,如何解决这个问题?

3 个解决方案

#1


7  

Angular has a feature called services which acts as a model for the application. It's where I'm communicating with my Rails backend:

Angular有一个称为服务的功能,它充当应用程序的模型。这是我与Rails后端通信的地方:

services/article.js

app.factory('Article', function($resource) {
  return $resource('http://localhost:3000/articles/:id', { id: '@id'},
  {
   'update': { method: 'PUT'}
  });
});

Even though the :id is specified on the end, it works just as well for going straight to the /articles path. The id will only be used where provided.

即使在最后指定了:id,它也可以直接进入/ articles路径。 id仅在提供的地方使用。

The rest of the work goes into the controller:

其余工作进入控制器:

controllers/articles.js

app.controller('NewPostCtrl', function($scope, Article) {
  $scope.newPost  = new Article();

  $scope.save = function() {
    Article.save({ article: $scope.article }, function() {
      // Optional function. Clear html form, redirect or whatever.
    });
  };

});

Originally, I assumed that the save() function that's made available through $resources was somewhat automatic. It is, but I was using it wrong. The default save() function can take up to four parameters, but only appears to require the data being passed to the database. Here, it knows to send a POST request to my backend.

最初,我假设通过$ resources提供的save()函数有点自动化。它是,但我错了。默认的save()函数最多可以使用四个参数,但只显示需要将数据传递给数据库。在这里,它知道向我的后端发送POST请求。

views/articles/index.html

<form name="form" ng-submit="save()">
    <input type="text" id="title" ng-model="article.title">
    <input type="text" id="body" ng-model="article.body">
    <input type="submit" value="Submit">
</form>

After getting the service setup properly, the rest was easy. In the controller, it's required to create a new instance of the resource (in this case, a new article). I created a new $scope variable that contains the function which invokes the save method I created in the service.

正确完成服务设置后,剩下的工作很简单。在控制器中,需要创建资源的新实例(在本例中为新文章)。我创建了一个新的$ scope变量,它包含调用我在服务中创建的save方法的函数。

Keep in mind that the methods created in the service can be named whatever you want. The importance of them is the type of HTTP request being sent. This is especially true for any RESTful app, as the route for GET requests is the same as for POST requests.

请记住,可以根据需要为服务中创建的方法命名。它们的重要性在于发送的HTTP请求的类型。对于任何RESTful应用程序尤其如此,因为GET请求的路由与POST请求的路由相同。

Below is the first solution I found. Thanks again for the responses. They were helpful in my experiments to learn how this worked!

以下是我找到的第一个解决方案。再次感谢您的回复。他们在我的实验中有助于了解这是如何工作的!

Original Solution: I finally fixed it, so I'll post my particular solution. However, I only went this route through lack of information how to execute this through an angular service. Ideally, a service would handle this kind of http request. Also note that when using $resource in services, it comes with a few functions one of which is save(). However, this also didn't work out for me.

原始解决方案:我终于修复了它,所以我将发布我的特定解决方案。但是,我只是通过缺乏信息如何通过角度服务来执行此路线。理想情况下,服务将处理此类http请求。另请注意,在服务中使用$ resource时,它附带了一些函数,其中一个函数是save()。但是,这对我来说也没有用。

articles.js controller

app.controller('FormCtrl', function($scope, $http) {
$scope.addPost = function() {
$scope.article = {
  'article': {
    'title'  : $scope.article.title,
    'body'   : $scope.article.body
  }
};

// Why can't I use Article.save() method from $resource?
    $http({
        method: 'POST',
        url: 'http://localhost:3000/articles',
    data: $scope.article
    });
};

});

Since Rails is the backend, sending a POST request to the /articles path invokes the #create method. This was a simpler solution for me to understand than what I was trying before.

由于Rails是后端,因此向/ articles路径发送POST请求会调用#create方法。对我来说,这是一个比我以前尝试过的更简单的解决方案。

To understand using services: the $resource gives you access to the save() function. However, I still haven't demystified how to use it in this scenario. I went with $http because it's function was clear.

要了解使用服务:$ resource允许您访问save()函数。但是,我仍然没有在这种情况下揭开如何使用它的神秘面纱。我用$ http去了,因为它的功能很明显。

Sean Hill has a recommendation which is the second time I've seen today. It may be helpful to anyone else wrestling with this issue. If I come across a solution which uses services, I'll update this.

肖恩希尔有一个建议,这是我今天第二次见到。对于解决这个问题的其他人来说,这可能会有所帮助。如果我遇到使用服务的解决方案,我会更新它。

Thank you all for your help.

感谢大家的帮助。

#2


2  

I've worked a lot with Angular and Rails, and I highly recommend using AngularJS Rails Resource. It makes working with a Rails backend just that much easier.

我在Angular和Rails上做了很多工作,我强烈建议使用AngularJS Rails Resource。它使得使用Rails后端变得更加容易。

https://github.com/FineLinePrototyping/angularjs-rails-resource

You will need to specify this module in your app's dependencies and then you'll need to change your factory to look like this:

您需要在应用程序的依赖项中指定此模块,然后您需要将工厂更改为如下所示:

app.factory('Article', function(railsResourceFactory) {
  return railsResourceFactory({url: '/articles', name: 'article');
});

Basically, based on the error that you are getting, what is happening is that your resource is not creating the correct article parameter. AngularJS Rails Resource does that for you, and it also takes care of other Rails-specific behavior.

基本上,根据您获得的错误,发生的事情是您的资源没有创建正确的文章参数。 AngularJS Rails Resource为您做到了这一点,它还负责其他特定于Rails的行为。

Additionally, $scope.newPost should not be Article.save(). You should initialize it with a new resource new Article() instead.

另外,$ scope.newPost不应该是Article.save()。您应该使用新资源new Article()来初始化它。

#3


0  

Until your input fields are blank, no value is stored in model and you POST empty article object. You can fix it by creating client side validation or set default empty string value on needed fields before save.

在输入字段为空之前,模型中不存储任何值,并且POST空文章对象。您可以通过创建客户端验证或在保存之前在所需字段上设置默认空字符串值来修复它。

First of all you should create new Article object in scope variable then pass newPost by params or access directly $scope.newPost in addArticle fn:

首先,您应该在范围变量中创建新的Article对象,然后通过params传递newPost或直接访问addArticle fn中的$ scope.newPost:

app.controller('ArticlesCtrl', function($scope, Article) {
  $scope.articles   = Article.query();
  $scope.newPost    = new Article();

  $scope.addArticle = function(newPost) {
    if (newPost.title == null) {
      newPost.title = '';
    }
    // or if you have underscore or lodash:
    // lodash.defaults(newPost, { title: '' });
    Article.save(newPost);
  };
});

If you want use CRUD operations you should setup resources like below:

如果您想使用CRUD操作,您应该设置如下资源:

$resource('/articles/:id.json', { id: '@id' }, { 
  update: {
    method: 'PUT'
  }
});

#1


7  

Angular has a feature called services which acts as a model for the application. It's where I'm communicating with my Rails backend:

Angular有一个称为服务的功能,它充当应用程序的模型。这是我与Rails后端通信的地方:

services/article.js

app.factory('Article', function($resource) {
  return $resource('http://localhost:3000/articles/:id', { id: '@id'},
  {
   'update': { method: 'PUT'}
  });
});

Even though the :id is specified on the end, it works just as well for going straight to the /articles path. The id will only be used where provided.

即使在最后指定了:id,它也可以直接进入/ articles路径。 id仅在提供的地方使用。

The rest of the work goes into the controller:

其余工作进入控制器:

controllers/articles.js

app.controller('NewPostCtrl', function($scope, Article) {
  $scope.newPost  = new Article();

  $scope.save = function() {
    Article.save({ article: $scope.article }, function() {
      // Optional function. Clear html form, redirect or whatever.
    });
  };

});

Originally, I assumed that the save() function that's made available through $resources was somewhat automatic. It is, but I was using it wrong. The default save() function can take up to four parameters, but only appears to require the data being passed to the database. Here, it knows to send a POST request to my backend.

最初,我假设通过$ resources提供的save()函数有点自动化。它是,但我错了。默认的save()函数最多可以使用四个参数,但只显示需要将数据传递给数据库。在这里,它知道向我的后端发送POST请求。

views/articles/index.html

<form name="form" ng-submit="save()">
    <input type="text" id="title" ng-model="article.title">
    <input type="text" id="body" ng-model="article.body">
    <input type="submit" value="Submit">
</form>

After getting the service setup properly, the rest was easy. In the controller, it's required to create a new instance of the resource (in this case, a new article). I created a new $scope variable that contains the function which invokes the save method I created in the service.

正确完成服务设置后,剩下的工作很简单。在控制器中,需要创建资源的新实例(在本例中为新文章)。我创建了一个新的$ scope变量,它包含调用我在服务中创建的save方法的函数。

Keep in mind that the methods created in the service can be named whatever you want. The importance of them is the type of HTTP request being sent. This is especially true for any RESTful app, as the route for GET requests is the same as for POST requests.

请记住,可以根据需要为服务中创建的方法命名。它们的重要性在于发送的HTTP请求的类型。对于任何RESTful应用程序尤其如此,因为GET请求的路由与POST请求的路由相同。

Below is the first solution I found. Thanks again for the responses. They were helpful in my experiments to learn how this worked!

以下是我找到的第一个解决方案。再次感谢您的回复。他们在我的实验中有助于了解这是如何工作的!

Original Solution: I finally fixed it, so I'll post my particular solution. However, I only went this route through lack of information how to execute this through an angular service. Ideally, a service would handle this kind of http request. Also note that when using $resource in services, it comes with a few functions one of which is save(). However, this also didn't work out for me.

原始解决方案:我终于修复了它,所以我将发布我的特定解决方案。但是,我只是通过缺乏信息如何通过角度服务来执行此路线。理想情况下,服务将处理此类http请求。另请注意,在服务中使用$ resource时,它附带了一些函数,其中一个函数是save()。但是,这对我来说也没有用。

articles.js controller

app.controller('FormCtrl', function($scope, $http) {
$scope.addPost = function() {
$scope.article = {
  'article': {
    'title'  : $scope.article.title,
    'body'   : $scope.article.body
  }
};

// Why can't I use Article.save() method from $resource?
    $http({
        method: 'POST',
        url: 'http://localhost:3000/articles',
    data: $scope.article
    });
};

});

Since Rails is the backend, sending a POST request to the /articles path invokes the #create method. This was a simpler solution for me to understand than what I was trying before.

由于Rails是后端,因此向/ articles路径发送POST请求会调用#create方法。对我来说,这是一个比我以前尝试过的更简单的解决方案。

To understand using services: the $resource gives you access to the save() function. However, I still haven't demystified how to use it in this scenario. I went with $http because it's function was clear.

要了解使用服务:$ resource允许您访问save()函数。但是,我仍然没有在这种情况下揭开如何使用它的神秘面纱。我用$ http去了,因为它的功能很明显。

Sean Hill has a recommendation which is the second time I've seen today. It may be helpful to anyone else wrestling with this issue. If I come across a solution which uses services, I'll update this.

肖恩希尔有一个建议,这是我今天第二次见到。对于解决这个问题的其他人来说,这可能会有所帮助。如果我遇到使用服务的解决方案,我会更新它。

Thank you all for your help.

感谢大家的帮助。

#2


2  

I've worked a lot with Angular and Rails, and I highly recommend using AngularJS Rails Resource. It makes working with a Rails backend just that much easier.

我在Angular和Rails上做了很多工作,我强烈建议使用AngularJS Rails Resource。它使得使用Rails后端变得更加容易。

https://github.com/FineLinePrototyping/angularjs-rails-resource

You will need to specify this module in your app's dependencies and then you'll need to change your factory to look like this:

您需要在应用程序的依赖项中指定此模块,然后您需要将工厂更改为如下所示:

app.factory('Article', function(railsResourceFactory) {
  return railsResourceFactory({url: '/articles', name: 'article');
});

Basically, based on the error that you are getting, what is happening is that your resource is not creating the correct article parameter. AngularJS Rails Resource does that for you, and it also takes care of other Rails-specific behavior.

基本上,根据您获得的错误,发生的事情是您的资源没有创建正确的文章参数。 AngularJS Rails Resource为您做到了这一点,它还负责其他特定于Rails的行为。

Additionally, $scope.newPost should not be Article.save(). You should initialize it with a new resource new Article() instead.

另外,$ scope.newPost不应该是Article.save()。您应该使用新资源new Article()来初始化它。

#3


0  

Until your input fields are blank, no value is stored in model and you POST empty article object. You can fix it by creating client side validation or set default empty string value on needed fields before save.

在输入字段为空之前,模型中不存储任何值,并且POST空文章对象。您可以通过创建客户端验证或在保存之前在所需字段上设置默认空字符串值来修复它。

First of all you should create new Article object in scope variable then pass newPost by params or access directly $scope.newPost in addArticle fn:

首先,您应该在范围变量中创建新的Article对象,然后通过params传递newPost或直接访问addArticle fn中的$ scope.newPost:

app.controller('ArticlesCtrl', function($scope, Article) {
  $scope.articles   = Article.query();
  $scope.newPost    = new Article();

  $scope.addArticle = function(newPost) {
    if (newPost.title == null) {
      newPost.title = '';
    }
    // or if you have underscore or lodash:
    // lodash.defaults(newPost, { title: '' });
    Article.save(newPost);
  };
});

If you want use CRUD operations you should setup resources like below:

如果您想使用CRUD操作,您应该设置如下资源:

$resource('/articles/:id.json', { id: '@id' }, { 
  update: {
    method: 'PUT'
  }
});