Daniel Buckmaster
Daniel Buckmaster

Reputation: 7186

AngularJS ng-submit fails on a Rails-generated form

I'm working with a Rails server (with Devise for authentication) and an AngularJS client. I've added a form generated by Rails to my client-side page, adding the ng-submit Angular directive like so:

<%= form_for("user",
    :url => user_session_path,
    :html => { "ng-submit" => "doSignIn()" }) do |f| %>

This generates a form with both action and ng-submit attributes, like this:

<form accept-charset="UTF-8" action="/users/sign_in" method="post" ng-submit="doSignIn()">

In the definition of the controller in the enclosing div, I have a doSignIn function that doesn't do anything at the moment:

$scope.doSignIn = function() {
    console.log($scope.email, $scope.password);
};

$scope.email and $scope.password are bound using ng-model. Or, at least, they're supposed to be - I can't tell, because clicking on submit always results in being directed to /users/sign_in. I was under the impression that using ng-submit would prevent the form from redirecting the user. I have also tried adding an ng-click to the submit button, using the same method, which also uses the doSignIn() method, and I've even tried passing it the event and calling event.preventDefault(). Nothing seems to stop me being redirected.

My goal is eventually to perform sign-in with AJAX, but for now, just proving that I can stop the automatic redirect would be great!

Upvotes: 3

Views: 2156

Answers (3)

Blaine Hatab
Blaine Hatab

Reputation: 1676

I found the cleanest and most logical way to solve this problem was to add $event to the ng-submit function. Then I just did $event.preventDefault() in my js file. My code looks like this:

_form.html.haml

%div{:'ng-controller' => 'FestivalCtrl'}
  = simple_form_for festival, :html => {:'ng-submit' => 'addFestival($event)', :action => nil} do |form|
    = form.input :name, :input_html => {:'ng-model' => 'newFestival.name'}, :label => 'Festival Name'
    = form.input :description, :input_html => {:'ng-model' => 'newFestival.description'}
    %button{:type => 'submit'}
      Submit Festival

  {{newFestival.name}}
  {{newFestival.description}}

  %ul
    %li{:'ng-repeat' => 'festival in festivals'}
      {{festival.name}}
      {{festival.description}}

festivals.js.coffee

app = angular.module('MFN', ['ngResource'])

app.factory 'Festival', ($resource) ->
  $resource('/festivals/:id', {id: '@id'}, {update: {method: 'PUT'}})


@FestivalCtrl = ($scope, Festival) ->  
  $scope.festivals = Festival.query()

  $scope.addFestival = ($event) ->
    $event.preventDefault()
    festival = Festival.save($scope.newFestival)
    $scope.festivals.push(festival)
    $scope.newFestival = {}

Upvotes: 2

Whellow
Whellow

Reputation: 398

I was under the impression that using ng-submit would prevent the form from redirecting the user.

This is only a correct assumption if the <form> does not have an action attribute associated with it. When you use the Rails form_for helper, it generates an action for you when you specify a url attribute.

To keep the form from submitting, you'll have to follow the advice of Abraham P above, and return false; where you do not want the form to submit.

Upvotes: 4

Abraham P
Abraham P

Reputation: 15471

You need to return false from your handler in order to prevent the form action from executing like so:

 $scope.doSignIn = function() {
     if($scope.email && $scope.password){
         return(true);
     else{
         return(false);
     }
 };

The assumption made above is that you want to submit if both the email and pasword are present, and do not want to submit otherwise.

Upvotes: 1

Related Questions