一个rails newbie,我在使用Angular JS提交表单时遇到了问题。我已在url
字段中指定/联系$http
,POST请求转到root
。
在我的导轨routes.rb
我有
Rails.application.routes.draw do
get 'home/index'
post 'home/contact' => "home#contact"
root 'home#index'
end
控制器非常基本
class HomeController < ApplicationController
def index
end
def contact
@captcha = params[:g-recpatcha-response]
@contact = ContactRequest.new(params[...])
....
end
end
更新
AngularJS包含在angular-rails
gem中,并使用require
application.js
属性进行了归档
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-sprockets
//= require jquery.easing.1.3.min
//= require jquery.sticky
//= require jquery.stellar.min
//= require wow.min
//= require custom
//= require contact_me.js
//= require jqBootstrapValidation.js
//= require angular
//= require_tree ./angular
//= require main.js
application.html.erb
的HTML代码段如下
<!DOCTYPE html>
<html>
<head>
<title>Etheron</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'https://www.google.com/recaptcha/api.js', :async => "", :defer => "" %>
<%= csrf_meta_tags %>
</head>
<body>
<%= render "layouts/header" %>
<%= yield %>
<%= render "layouts/footer" %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= debug(params) if Rails.env.development? %>
</body>
</html>
,表单包含在index.html.erb
<div ng-app="etherOn" class="form-contact">
<div class="required">
<p>( <span>*</span> fields are required )</p>
</div>
<form ng-controller="formController" ng-submit="contactRequest()" name="sentMessage" id="contactForm" novalidate>
<div class="row">
<div class="col-md-6">
<div class="row control-group">
<div class="form-group col-xs-12 controls" ng-class="{ 'has-error' : formData.name.$invalid && !formData.name.$pristine }">
<label>Name<span>*</span></label>
<input type="text" class="form-control" placeholder="Name" id="name" required ng-model="formData.name">
<!-- <p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">You name is required.</p> -->
</div>
</div>
</div>
<div class="col-md-6">
<div class="row control-group">
<div class="form-group col-xs-12 controls" ng-class="{ 'has-error' : formData.email.$invalid && !formData.email.$pristine }">
<label>Email Address<span>*</span></label>
<input type="email" class="form-control" placeholder="Email Address" id="email" required ng-model="formData.email">
<!-- <p ng-show="userForm.email.$invalid && !userForm.email.$pristine" class="help-block">You name is required.</p> -->
</div>
</div>
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 controls" ng-class="{ 'has-error' : formData.phone.$invalid && !formData.phone.$pristine}" >
<label>Phone Number<span>*</span></label>
<input type="tel" class="form-control" placeholder="Phone Number" id="phone" required ng-model="formData.phone">
<!-- <p ng-show="userForm.phone.$invalid && !userForm.phone.$pristine" class="help-block">You name is required.</p> -->
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 controls" ng-class="{ 'has-error' : formData.message.$invalid && !formData.message.$pristine}" >
<label>Message<span>*</span></label>
<textarea rows="5" class="form-control" placeholder="Message" id="message" required ng-model="formData.message"></textarea>
<!-- <p ng-show="userForm.message.$invalid && !userForm.message.$pristine" class="help-block">You name is required.</p> -->
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 controls">
<div class="g-recaptcha" data-sitekey="6Lf2xAkTAAAAAOpJvpHn10HDPBTGP55ROzl01nIP"> </div>
<!-- -->
</div>
</div>
<br>
<div id="success"></div>
<div class="row">
<div class="form-group col-xs-12">
<button type="submit" class="btn btn-theme-bg btn-lg">Send Message</button>
</div>
</div>
</form>
</div><!--contact form-->
javascript代码位于main.js
文件中,用于表单提交
var app = angular.module("etherOn", []);
app.controller("formController", function($http, $scope) {
$scope.formData = {};
console.log("submit form");
$scope.contactRequest = function() {
if($scope.formData.g-recaptcha-response === ""){ //if string is empty
// TODO: use bootstrap sweet modals here
alert("Please resolve the captcha and submit!")
}else{
var post_data = $.param($scope.formData);
$http.post({
method: 'POST',
url: 'home/contact',
data: post_data,
headers : { "X-CSRF-Token" : $('meta[name="csrf-token"]').attr('content'),'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }
}).success(function(response){
console.log(response);
if(response.error === 0){
alert("Successfully verified and signed up the user");
}else{
alert("User verification failed");
}
})
.error(function(error){
})
}
}
});
问题是AngularJS表单提交代码永远不会被调用,从不同的tutuments尝试了很多片段,没有帮助。有一些详细示例,但它们都基于ActiveRecord,我不想在这里使用,因为我所做的就是使用sendgrid生成一个电子邮件,表单已提交。
答案 0 :(得分:0)
我想也许你错过了表单提交网址和$ http网址。
表单标记提交网址与$ http网址不同。
首先,您的表单标记没有操作。所以默认操作网址是“/”(现在是页面)
因为表单操作url“/”,表单提交为“/”
我认为你错过了关于上述2的更多观点。
也许偶数2号进程($ http post例程)不起作用
错误点
Rails有检查例程csrf-token。因此,当您发布操作时,操作跳过before_filter:verify_authenticity_token(A)或在angularjs中,将csrf-token添加到$ http标头。 (B)
#(A)
skip_before_filter :verify_authenticity_token
#(B)
$http({
method : 'POST',
url : '/contact',
data : $.param($scope.formData), // pass in data as strings
headers : { "X-CSRF-Token" : $('meta[name="csrf-token"]').attr('content') }
})
// $('meta[name="csrf-token"]') tag is generated by layout <%= csrf_meta_tags %>
答案 1 :(得分:0)
有多个问题导致这种情况,主要是因为我混淆了事情,我添加了一个角度重新接收模块,它没有正确加载并且执行了脚本的其余部分失败,删除了它,修复了角形状然后重新 - 启用验证码以使工作正常。谢谢你们的帮助!
这是结构,现在可以使用
application.js
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-sprockets
//= require jquery.easing.1.3.min
//= require jquery.sticky
//= require jquery.stellar.min
//= require wow.min
//= require custom
//= require angular
//= require angular-recaptcha.min.js
//= require main.js
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Etheron</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'https://www.google.com/recaptcha/api.js?render=explicit&onload=vcRecaptchaApiLoaded', :async => "", :defer => "",
:type =>"text/javascript" %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true , :type =>"text/javascript" %>
<%= csrf_meta_tags %>
</head>
<body ng-app="etherOn">
<%= render "layouts/header" %>
<%= yield %>
<%= render "layouts/footer" %>
<%= debug(params) if Rails.env.development? %>
</body>
</html>
包含在index.html.erb
<div class="form-contact" ng-controller="formController">
<div class="required">
<p>( <span>*</span> fields are required )</p>
</div>
<div id="success" class="alert alert-success" ng-show="messages" ng-bind="messages"></div>
<form name="sentMessage" role="form" novalidate>
<div class="row">
<div class="col-md-6">
<div class="row control-group">
<div class="form-group col-xs-12 controls">
<label>Name<span>*</span></label>
<span class="label label-danger" ng-show="submitted && sentMessage.name.$error.required">Required!</span>
<input type="text" class="form-control" placeholder="Name" name="name" required ng-model="contact.name">
</div>
</div>
</div>
<div class="col-md-6">
<div class="row control-group">
<div class="form-group col-xs-12 controls">
<label>Email Address<span>*</span></label>
<span class="label label-danger" ng-show="submitted && sentMessage.email.$error.required">Required!</span>
<input type="email" class="form-control" placeholder="Email Address" name="email" required ng-model="contact.email">
</div>
</div>
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 controls">
<label>Phone Number<span>*</span></label>
<span class="label label-danger" ng-show="submitted && sentMessage.phone.$error.required">Required!</span>
<input type="tel" class="form-control" placeholder="Phone Number" name="phone" required ng-model="contact.phone">
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 controls">
<label>Message<span>*</span></label>
<span class="label label-danger" ng-show="submitted && sentMessage.message.$error.required">Required!</span>
<textarea rows="5" class="form-control" placeholder="Message" name="message" required ng-model="contact.message"></textarea>
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 controls">
<label>Verify<span>*</span></label>
<span class="label label-danger" ng-show="submitted && response === null">Required!</span>
<div vc-recaptcha theme="'light'"
key="model.key"
on-create="setWidgetId(widgetId)"
on-success="setResponse(response)"></div>
</div>
</div>
<br>
<div class="row">
<div class="form-group col-xs-12">
<button type="submit" class="btn btn-theme-bg btn-lg" ng-click="contactRequest(sentMessage)">Send Message</button>
</div>
</div>
</form>
</div><!--contact form-->
和脚本
angular.module("etherOn", ['vcRecaptcha'])
.config([
"$httpProvider", function($httpProvider) {
$httpProvider.defaults.headers.post['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
}
])
.controller("formController",["vcRecaptchaService","$http","$scope", "$timeout", function(vcRecaptchaService,$http, $scope, $timeout) {
$scope.contact = {};
$scope.submitted = false;
$scope.response = null;
$scope.widgetId = null;
$scope.model = {
key: "6Lf2xAkTAAAAAOpJvpHn10HDPBTGP55ROzl01nIP"
};
$scope.setResponse = function (response) {
$scope.response = response;
};
$scope.setWidgetId = function (widgetId) {
$scope.widgetId = widgetId;
};
$scope.contactRequest = function(form) {
// Trigger validation flag.
$scope.submitted = true;
// If form is invalid, return and let AngularJS show validation errors.
if (form.$invalid) {
return;
}else{
var post_data = { //prepare payload for request
'name':$scope.contact.name,
'email':$scope.contact.email,
'phone':$scope.contact.phone,
'message':$scope.contact.message,
'captcha':$scope.response //send g-captcah-reponse to our server
}
console.log(post_data);
$http.post(
'home/contact',post_data
).success(function(response){
console.log(response);
if(response.error === 0){
$scope.messages = "Thanks!" + $scope.name + "for your request! We will get back to you shortly"
}else{
$scope.messages = "We are sorry but your request was not processed, please try again."
}
})
.error(function(error){
$scope.messages = "We are sorry but your request was not processed, please try again."
})
.finally(function() {
// Hide status messages after three seconds.
$timeout(function() {
$scope.messages = null;
}, 5000);
vcRecaptchaService.reload($scope.widgetId);
});
}
}
}]);