AngularJS 提交表单的方式 已翻译 100%

oschina 投递于 2014/06/21 17:16 (共 13 段, 翻译完成于 06-24)
阅读 60933
收藏 126
9
加载中

A lot of developers were submitting forms before AngularJS came out. There were so many different ways to submit forms that it could drive a person crazy… and they still can.

Today we’ll be looking at a simple form that used to be submitted using PHP and how to convert that to Angular. Using Angular for forms was one of those AHA moments for me. Even though it barely scratches the surface of Angular, it helps a user see the potential after seeing forms submitted and understanding the idea of two-way data-binding.

We will look at processing a form with just plain jQuery. The work needed to do this will be primarily in the javascript. We will submit the form, show errors, add error classes, and show/hide messages in javascript.

已有 1 人翻译此段
我来翻译

After that, we will be using Angular. The bulk of the work that was needed before will go away and lots of the things we did before (showing errors, adding classes, showing/hiding messages) will be so much simpler. Let’s dive in.

Submitting Forms with Just jQuery and AJAX: If you want to view a full article on submitting a form just using jQuery and AJAX, view our other article: Submitting AJAX Forms with jQuery.

Our Sample Form

We’ll be looking at two ways to submit this form:

  • The Old Way: AJAX Form with jQuery and PHP

  • The New Way: AJAX Form with AngularJS and PHP

Take a look at what we’ll be building. Super simple.

submitting-forms-with-angular

Form Requirements

  • Process the form without page refresh

  • Enter Name and Superhero Alias

  • Show errors if there are any

  • Turn inputs red if there are errors

  • Show success message if all is good

File Structure

We’ll only need two files to demonstrate.

  • index.html

  • process.php

已有 1 人翻译此段
我来翻译

Processing the Form

Let’s setup the PHP to process our form. This will be very minimal and will use http POST to get the form data.

Processing the Form: This won’t be that important to us. You can use any other language to process your form that you like.

// process.php

<?php

$errors         = array();      // array to hold validation errors
$data             = array();         // array to pass back data

// validate the variables ======================================================
    if (empty($_POST['name']))
        $errors['name'] = 'Name is required.';

    if (empty($_POST['superheroAlias']))
        $errors['superheroAlias'] = 'Superhero alias is required.';

// return a response ===========================================================

    // response if there are errors
    if ( ! empty($errors)) {

        // if there are items in our errors array, return those errors
        $data['success'] = false;
        $data['errors']  = $errors;
    } else {

        // if there are no errors, return a message
        $data['success'] = true;
        $data['message'] = 'Success!';
    }

    // return all our data to an AJAX call
    echo json_encode($data);

This is a very simple form processing script. We will just check if the data exists. If it does exist, don’t do anything. If it doesn’t exist, add a message to our $errors array.

To return our data to an AJAX call, we have to echo and json_encode. This is all we have to do with our PHP form processing. It will be the same for processing a form using normal jQuery AJAX or Angular.

已有 1 人翻译此段
我来翻译

Showing the Form

Let’s create our HTML that will show our form.

<!-- index.html -->

<!doctype html>
<html>
<head>
    <title>Angular Forms</title>

    <!-- LOAD BOOTSTRAP CSS -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">

    <!-- LOAD JQUERY -->
        <!-- when building an angular app, you generally DO NOT want to use jquery -->
        <!-- we are breaking this rule here because jQuery's $.param will help us send data to our PHP script so that PHP can recognize it -->
        <!-- this is jQuery's only use. avoid it in Angular apps and if anyone has tips on how to send data to a PHP script w/o jQuery, please state it in the comments -->
       <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>

    <!-- PROCESS FORM WITH AJAX (OLD) -->
    <script>
        <!-- WE WILL PROCESS OUR FORM HERE -->
    </script>
</head>
<body>
<div class="container">
<div class="col-md-6 col-md-offset-3">

    <!-- PAGE TITLE -->
    <div class="page-header">
        <h1><span class="glyphicon glyphicon-tower"></span> Submitting Forms with Angular</h1>
    </div>

    <!-- SHOW ERROR/SUCCESS MESSAGES -->
    <div id="messages"></div>

    <!-- FORM -->
    <form>
        <!-- NAME -->
        <div id="name-group" class="form-group">
            <label>Name</label>
            <input type="text" name="name" class="form-control" placeholder="Bruce Wayne">
            <span class="help-block"></span>
        </div>

        <!-- SUPERHERO NAME -->
        <div id="superhero-group" class="form-group">
            <label>Superhero Alias</label>
            <input type="text" name="superheroAlias" class="form-control" placeholder="Caped Crusader">
            <span class="help-block"></span>
        </div>

        <!-- SUBMIT BUTTON -->
        <button type="submit" class="btn btn-success btn-lg btn-block">
            <span class="glyphicon glyphicon-flash"></span> Submit!
        </button>
    </form>

</div>
</div>
</body>
</html>

Now we have our form. We’ve also used Bootstrap to make it not super ugly. Using the Bootstrap syntax, there is also a spot under each input to show a line of text for our errors.

submitting-forms-with-angular

已有 1 人翻译此段
我来翻译

Submit the Form with jQuery

Let’s go through the process of submitting the form with jQuery now. We will add all the code into our empty <script> tags.

<!-- index.html -->

...

    <!-- PROCESS FORM WITH AJAX (OLD) -->
    <script>
        $(document).ready(function() {

            // process the form
            $('form').submit(function(event) {

                // remove the past errors
                $('#name-group').removeClass('has-error');
                $('#name-group .help-block').empty();
                $('#superhero-group').removeClass('has-error');
                $('#superhero-group .help-block').empty();

                // remove success messages
                $('#messages').removeClass('alert alert-success').empty();

                // get the form data
                var formData = {
                    'name'                 : $('input[name=name]').val(),
                    'superheroAlias'     : $('input[name=superheroAlias]').val()
                };

                // process the form
                $.ajax({
                    type         : 'POST',
                    url         : 'process.php',
                    data         : formData,
                    dataType     : 'json',
                    success     : function(data) {

                        // log data to the console so we can see
                        console.log(data);

                        // if validation fails
                        // add the error class to show a red input
                        // add the error message to the help block under the input
                        if ( ! data.success) {

                            if (data.errors.name) {
                                $('#name-group').addClass('has-error');
                                $('#name-group .help-block').html(data.errors.name);
                            }

                            if (data.errors.superheroAlias) {
                                $('#superhero-group').addClass('has-error');
                                $('#superhero-group .help-block').html(data.errors.superheroAlias);
                            }

                        } else {

                            // if validation is good add success message
                            $('#messages').addClass('alert alert-success').append('<p>' + data.message + '</p>');
                        }
                    }
                });

                // stop the form from submitting and refreshing
                event.preventDefault();
            });

        });
    </script>

...

There’s a lot of code here to process the form. We have code to get the variables from the form, send it to our form using AJAX, check if there are any errors, and show a success message. On top of all that, every time the form is submitted, we want it to clear the past errors. Quite a lot of code.

Now if there is an error:

submitting-error

Or if there is a successful submission:

submit-success

Now let’s look at the same form, submitted with Angular. Remember, we don’t have to change anything about how our PHP processes the form and our application will function the same (showing errors and successes in the same places).

已有 1 人翻译此段
我来翻译

Submit the Form with Angular

We are going to set up our Angular application right inside the <script> tags we used earlier. So just delete everything inside and let’s begin.

Setting Up An Angular Application

The steps to set up our Angular application are:

  1. Load angular

  2. Set up a module

  3. Set up controller

  4. Apply module and controller to HTML

  5. Set up 2-way bound variables

  6. Set up errors and messages

It sounds like a lot, but in the end, we’ll use far less code and it will be much cleaner. It will also be much easier to create larger forms with many more inputs.

Angular Module and Controller

Let’s load up Angular and create our module and controller.

<!-- index.html -->

...

    <!-- LOAD JQUERY -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    <!-- LOAD ANGULAR -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>

    <!-- PROCESS FORM WITH AJAX (NEW) -->
    <script>

        // define angular module/app
        var formApp = angular.module('formApp', []);

        // create angular controller and pass in $scope and $http
        function formController($scope, $http) {

        }

    </script>
</head>

<!-- apply the module and controller to our body so angular is applied to that -->
<body ng-app="formApp" ng-controller="formController">

...

We now have the foundation for our Angular app. We’ve loaded Angular, created a module and controller, and applied it to our site.

Next we will be showing off how 2-way binding works.

已有 1 人翻译此段
我来翻译

2-Way Data-Binding

This is one of the core ideas of Angular and one of its most powerful. From the Angular docs: “Data-binding in Angular web apps is the automatic synchronization of data between the model and view.” This means that the step where we have to grab data from the form using $('input[name=name]').val() is not required.

We bind data to a variable in Angular, and whenever it changes in either the Javascript or in the view, it changes in both.

To demonstrate data-binding, we’ll get our form inputs to populate a variable formData automagically. Let’s look back at our Angular controller that we applied to our page. We passed in $scope and $http.

$scope: The glue between application controller and the view. Basically variables are passed to and from our controller and view using $scope. For a more detailed definition, check out the docs.
$http: The Angular service that will help us do our POST request. For more information, check out the docs.

已有 1 人翻译此段
我来翻译

Getting the Variables Using Data-Binding

Alright, enough talk. Let’s apply this information to our form. It’s way simpler than it sounded above. We will add a line to the Angular controller and a line to the view.

<!-- index.html -->

...

    <!-- PROCESS FORM WITH AJAX (NEW) -->
    <script>

        // define angular module/app
        var formApp = angular.module('formApp', []);

        // create angular controller and pass in $scope and $http
        function formController($scope, $http) {

            // create a blank object to hold our form information
            // $scope will allow this to pass between controller and view
            $scope.formData = {};

        }

...

Now we have set up a formData object. Let’s populate it with our form inputs. Before we had to explicitly call each input and get its val(). Not anymore. We will use ng-model to bind a specific input to a variable.

<!-- index.html -->

...

    <!-- FORM -->
    <form>
        <!-- NAME -->
        <div id="name-group" class="form-group">
            <label>Name</label>
            <input type="text" name="name" class="form-control" placeholder="Bruce Wayne" ng-model="formData.name">
            <span class="help-block"></span>
        </div>

        <!-- SUPERHERO NAME -->
        <div id="superhero-group" class="form-group">
            <label>Superhero Alias</label>
            <input type="text" name="superheroAlias" class="form-control" placeholder="Caped Crusader" ng-model="formData.superheroAlias">
            <span class="help-block"></span>
        </div>

        <!-- SUBMIT BUTTON -->
        <button type="submit" class="btn btn-success btn-lg btn-block">
            <span class="glyphicon glyphicon-flash"></span> Submit!
        </button>
    </form>

    <!-- SHOW DATA FROM INPUTS AS THEY ARE BEING TYPED -->
    <pre>
        {{ formData }}
    </pre>

...

Now, Angular will now that each input is bound to formData. As you type into each input box, you can see the formData object being populated! It’s magic!

You do not need to use the word $scope in the view. Everything is considered to be nested inside of $scope.

已有 2 人翻译此段
我来翻译

Processing the Form

In our old form, we had to use jQuery to submit the form using $('form').submit(). Now we will use an Angular feature called ng-submit. To do this, we will add a controller function to process the form, and tell our form to use that controller function..

<!-- index.html -->

...

    <!-- PROCESS FORM WITH AJAX (NEW) -->
    <script>

        // define angular module/app
        var formApp = angular.module('formApp', []);

        // create angular controller and pass in $scope and $http
        function formController($scope, $http) {

            // create a blank object to hold our form information
            // $scope will allow this to pass between controller and view
            $scope.formData = {};

            // process the form
            $scope.processForm = function() {

            };

        }

...

    <!-- FORM -->
    <form ng-submit="processForm()">

...

Now our form knows to use that controller function when it is submitted. Now that we have that in place, let’s actually process the form using $http.

The syntax for processing a form will look very similar to the original way of doing it. The benefit is that we don’t have to grab our form data manually, or inject, hide, or add classes to show errors or success messages.

<!-- index.html -->

...

// process the form
$scope.processForm = function() {
    $http({
        method  : 'POST',
        url     : 'process.php',
        data    : $.param($scope.formData),  // pass in data as strings
        headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
    })
        .success(function(data) {
            console.log(data);

            if (!data.success) {
                // if not successful, bind errors to error variables
                $scope.errorName = data.errors.name;
                $scope.errorSuperhero = data.errors.superheroAlias;
            } else {
                // if successful, bind success message to message
                $scope.message = data.message;
            }
        });
};

...

That’s it for our form! None of that adding or removing classes. We don’t have to clear the errors every time we submit the form. We just have to bind the variables and the view will take care of the rest. This is great since the controller is for the data and the view is for showing the data.

已有 1 人翻译此段
我来翻译

jQuery POST vs Angular POST Sometimes you may see that your POST isn’t showing data on the server. This is because of the difference in the way jQuery and Angular serialize and send data. This comes down to the server language you are using and its ability to understand Angular’s data.

The above code is for a PHP server and jQuery is needed for the $.param function. There are ways to do it without jQuery but that’s pretty much the only reason jQuery was included for this example. Because it was easier.

The below cleaner syntax will work based on your server-side language. For more information on making AngularJS AJAX calls, read this great article: Make AngularJS $http Service Behave Like jQuery AJAX

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(18)

像Null一样
在用anglurJs验证表单的时候,你的js代码写的有问题,问题如下
//1,建立模块
var formApp = angular.module('formApp', []);
//2,你建立的模块并没有和controller建立联系 发生错误
function formController($scope, $http) {
}

我将代码修改如下:
//1,建立模块
var formApp = angular.module('formApp', []);
    //2,模块与控制层建立关联
    formApp.controller('formController',['$scope', '$http', function($scope, $http) {
     $scope.formData = {};
}
这样就解决了bug ,这是我的个人理解,如果有错请指教
一公斤梦想
一公斤梦想
这篇文章还不错,只是英语部分忽略不看了
巴林的狗尾草
巴林的狗尾草

引用来自“CodingKu”的评论

我做一个后台系统,一直纠结于用不用iframe,感觉用iframe吧,不是很高大上。不用iframe用EasyUI等框架吧,感觉涉及到的东西还不少,而且还有BUG。如果是纯div然后每次form submit后,用jQuery改变DOM吧,又觉得改了太多的DOM。用AngularJS会不会好些
不要用angular,不合适
lnyu
lnyu
augular已死
随便写一个
Hidjs
Ken-ZLK
Ken-ZLK
1
纯洁徐
纯洁徐
yourname是一个变量
Andrew1985
Andrew1985
我想请教下,我测试的Hello {{yourname || 'World'}}! 为啥ng-app相当于没作用,括号一直都存在。
返回顶部
顶部