Угловая форма POST переходит к неправильному действию URL

0

У рельсов новичок, у меня проблемы с отправкой формы с помощью 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 и включается с использованием атрибута 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

HTML-фрагмент для 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', :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 для 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 никогда не вызывается, пробовал немало фрагментов из разных папок без помощи. Есть пример detaild, но все они основаны на ActiveRecord, который я не хочу использовать здесь, поскольку все, что я делаю, - это генерировать электронное письмо с использованием sendgrid, который отправляется формой.

2 ответа

0
Лучший ответ

Там несколько проблем, вызвавших это, прежде всего из-за того, что я перепутал вещи, я добавил модуль угловой-recaptcha, который не загружался должным образом и не выполнял оставшуюся часть исполняемого скрипта, удалял его, фиксировал угловую форму, а затем снова включал captcha чтобы все работало. Спасибо вам за помощь!

здесь структура и она работает сейчас

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 в 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);
                });
            }   
        }
    }]);
0

Я думаю, возможно, вы пропустили форму submit url и URL http.

Тэг отправки тега формы отличается от url $ http.

Прежде всего, ваш тег формы не имеет никаких действий. Таким образом, URL-адрес действия по умолчанию - "/" (теперь страница)

  1. Когда форма отправляется, выполняется ng-submit = "".
  2. ng-submit блок $ http выполнен. ($ http является асинхронным блоком)
  3. После того, как ng-submit будет завершен, форма будет отправлена!

поэтому из-за формы action url "/", форма submit "/"

И я думаю, вы пропустите больше очков примерно 2.

Может быть, даже процесс номер 2 (почтовая программа $ http) не работает

для пропущенного пункта

Rails имеет проверку подпрограммы csrf-токена. поэтому, когда ваше сообщение в действии, действие пропустило before_filter: verify_authenticity_token (A) или в angularjs, добавьте csrf-токен в заголовки $ http. (В)

#(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 %>
  • 0
    Я думаю, проблема в том, что этот угловой кодовый блок никогда не вызывается, я добавил console.log('submit from angular') в качестве первой строки этой функции, он не печатается в консоли.
  • 0
    Кроме того, согласно документации по ngSubmit, форма не должна иметь атрибута action, поэтому я не поместил его туда
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню