<!DOCTYPE html> <html> <head> <script src="angular.js"></script> <script src="script.js"></script> <style> label { display: inline-block; width: 120px; vertical-align: middle; } input { display: inline-block; vertical-align: middle; } { border: solid red 2px; } textarea { width: 300px; height: 80px; } </style> </head> <body ng-app="mainModule"> <div ng-controller="mainController"> <h3>1. Standard form submission</h3> <form name="personForm1" action="server.php" method="post" novalidate> <label for="firstNameEdit1">First name:</label> <input id="firstNameEdit1" type="text" name="firstName" ng-model="person1.firstName" required /><br /> <label for="lastNameEdit1">Last name:</label> <input id="lastNameEdit1" type="text" name="lastName" ng-model="person1.lastName" required /><br /> <br /> <button type="submit" ng-disabled="personForm1.$invalid">Submit</button> </form> <br /> <h3>2. AJAX form submission with ng-submit</h3> <form name="personForm2" ng-submit="submitData(person2, 'ajaxSubmitResult1')" novalidate> <label for="firstNameEdit2">First name:</label> <input id="firstNameEdit2" type="text" name="firstName" ng-model="person2.firstName" required /><br /> <label for="lastNameEdit2">Last name:</label> <input id="lastNameEdit2" type="text" name="lastName" ng-model="person2.lastName" required /><br /> <br /> <button type="submit" ng-disabled="personForm2.$invalid">Submit</button> </form> <br /> <strong><label for="submitDebugText1">Submit result:</label></strong><br /> <textarea id="submitDebugText1">{{ajaxSubmitResult1 | json}}</textarea><br /> <br /> <h3>3. AJAX form submission with ng-click</h3> <form name="personForm3" novalidate> <label for="firstNameEdit3">First name:</label> <input id="firstNameEdit3" type="text" name="firstName" ng-model="person3.firstName" required /><br /> <label for="lastNameEdit3">Last name:</label> <input id="lastNameEdit3" type="text" name="lastName" ng-model="person3.lastName" required /><br /> <br /> <button type="submit" ng-click="submitData(person3, 'ajaxSubmitResult2')" ng-disabled="personForm3.$invalid">Submit</button> </form> <br /> <strong><label for="submitDebugText2">Submit result:</label></strong><br /> <textarea id="submitDebugText2">{{ajaxSubmitResult2 | json}}</textarea> </div> </body> </html>
angular.module("mainModule", []) .controller("mainController", function ($scope, $http) { $scope.person1 = {}; $scope.person2 = {}; $scope.person3 = {}; $scope.submitData = function (person, resultVarName) { var config = { params: { person: person } }; $"server.php", null, config) .success(function (data, status, headers, config) { $scope[resultVarName] = data; }) .error(function (data, status, headers, config) { $scope[resultVarName] = "SUBMIT ERROR"; }); }; });
<?php if ($_SERVER["REQUEST_METHOD"] === "POST") { if (isset($_POST["firstName"]) && isset($_POST["lastName"])) { // Standard form submission $result = "RECEIVED PERSON DATA:" . "<br />firstName = " . $_POST["firstName"] . "<br />lastName = " . $_POST["lastName"]; } else if (isset($_GET["person"])) { // AJAX form submission $person = json_decode($_GET["person"]); $result = json_encode(array( "receivedFirstName" => $person->firstName, "receivedLastName" => $person->lastName)); } else { $result = "INVALID REQUEST DATA"; } echo $result; } ?>



A form would be mostly useless without submitting its data to the server. AngularJS gives us different options for the form submission. Let's explore them.

Point 1 of the example shows the standard form submission that we can commonly have in HTML. We just choose the method with the method attribute and the server URL that handles the submission by specifying the action attribute. In our script.js file we've defined the person1 model variable on the scope to manage the input elements validation (remember that we need model variables associated to the input elements for the validation to work). We also did something more: with the ng-disabled directive we let the button be enabled only if personForm1 is valid. We've specified even the novalidate attribute on the form element because we don't want the browser validation to interfere with the one provided by AngularJS. The form submission here has no difference with a standard HTML form submission because whenever we press the button (notice the submit type) the form fields (defined with the name attributes on the input elements) are sent to the server.php page that reads them and sends back a response showing that the data was correctly received. The page is redirected to server.php so we actually leave our current page.

In many cases it's more appropriate to stay in the current page and send just the data to the server. This is the AJAX form submission.

Point 2 shows the use of the ng-submit directive to obtain an AJAX form submission. To work with it, we must avoid specifying the action attribute on the form element, this prevents the standard form submission so we don't have to leave the current page. Whenever the ENTER key is pressed inside an input field or a button with the submit type is pressed, the ng-submit handler function is called (if we have more buttons in the form, but their type is not submit, pressing them will not trigger the ng-submit handler). Inside the handler function we can choose our preferred way to submit the data to the server. In this example we simply use the $http service to issue a POST call and send to the server the whole person2 model variable as a JSON object, then the server will send it back to us with modified fields just to show that the request has been handled correctly and the right data has been received from the client form.

Point 3 is basically like point 2, but here we use a different event handler to deal with the form submission. Here we use the ng-click directive to specify an handler on the submit button. It's important to note that the handler function will be called whenever the user presses the submit button, but also when the ENTER key is pressed inside any of the input fields. What happens when there's more than one button with type submit in the form and the user presses the ENTER key inside an input element? And what if there are other buttons in the form whose type is not submit? Here are the answers:

  • if the form contains more than one button with type submit and the user presses the ENTER key inside an input element, only the ng-click handler of the button that appears first in the form is called
  • if the form contains other buttons of different types (e.g. type button), their ng-click handlers are not called when the user presses the ENTER key inside the input elements, only an handler of a submit button is automatically called

Always keep in mind that pressing the ENTER key inside the input elements of a form triggers both ng-submit and ng-click so you don't want to mix them. Always use only one of them, so choose between the form submission presented in point 2 or the one presented in point 3 of the example.