├── LICENSE ├── README.md ├── index.html ├── js ├── app.js └── modules │ └── promise-tracker.js └── response.json /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Juan Pablo Novillo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AngularJS form example 2 | 3 | This repository contains a dummy contact form powered by AngularJS. 4 | 5 | See it in action at http://juampy72.github.io/angularjs_form 6 | 7 | There is a step by step tutorial on this form at [the Lullabot Blog](https://www.lullabot.com/blog/article/processing-forms-angularjs). 8 | 9 | ## Installation 10 | 11 | Simply clone this repository on a directory accessible from your local web server. 12 | Then, open index.html from a web browser. 13 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AngularJS Form 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

AngularJs form

13 | 14 |

This is an AngularJs based form. It uses a controller to handle form validation and submission.

15 |

Find a step by step tutorial on this form at the Lullabot Blog.

16 | Fork me on GitHub 17 | 18 |
19 |
20 |
Sending…
21 |
22 |
23 | 24 | Required! 25 | 26 |
27 | 28 |
29 | 30 | Required! 31 | Invalid email! 32 | 33 |
34 | 35 |
36 | 37 | Required! 38 | 41 |
42 | 43 |
44 | 45 | Invalid URL format! 46 | 47 |
48 | 49 |
50 | 51 | Required! 52 | 53 |
54 | 55 | 56 |
57 |
58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * AngularJS module to process a form. 3 | */ 4 | angular.module('myApp', ['ajoslin.promise-tracker']) 5 | .controller('help', function ($scope, $http, $log, promiseTracker, $timeout) { 6 | $scope.subjectListOptions = { 7 | 'bug': 'Report a Bug', 8 | 'account': 'Account Problems', 9 | 'mobile': 'Mobile', 10 | 'user': 'Report a Malicious User', 11 | 'other': 'Other' 12 | }; 13 | 14 | // Inititate the promise tracker to track form submissions. 15 | $scope.progress = promiseTracker(); 16 | 17 | // Form submit handler. 18 | $scope.submit = function(form) { 19 | // Trigger validation flag. 20 | $scope.submitted = true; 21 | 22 | // If form is invalid, return and let AngularJS show validation errors. 23 | if (form.$invalid) { 24 | return; 25 | } 26 | 27 | // Default values for the request. 28 | var config = { 29 | params : { 30 | 'callback' : 'JSON_CALLBACK', 31 | 'name' : $scope.name, 32 | 'email' : $scope.email, 33 | 'subjectList' : $scope.subjectList, 34 | 'url' : $scope.url, 35 | 'comments' : $scope.comments 36 | }, 37 | }; 38 | 39 | // Perform JSONP request. 40 | var $promise = $http.jsonp('response.json', config) 41 | .success(function(data, status, headers, config) { 42 | if (data.status == 'OK') { 43 | $scope.name = null; 44 | $scope.email = null; 45 | $scope.subjectList = null; 46 | $scope.url = null; 47 | $scope.comments = null; 48 | $scope.messages = 'Your form has been sent!'; 49 | $scope.submitted = false; 50 | } else { 51 | $scope.messages = 'Oops, we received your request, but there was an error processing it.'; 52 | $log.error(data); 53 | } 54 | }) 55 | .error(function(data, status, headers, config) { 56 | $scope.progress = data; 57 | $scope.messages = 'There was a network error. Try again later.'; 58 | $log.error(data); 59 | }) 60 | .finally(function() { 61 | // Hide status messages after three seconds. 62 | $timeout(function() { 63 | $scope.messages = null; 64 | }, 3000); 65 | }); 66 | 67 | // Track the request and show its progress to the user. 68 | $scope.progress.addPromise($promise); 69 | }; 70 | }); 71 | -------------------------------------------------------------------------------- /js/modules/promise-tracker.js: -------------------------------------------------------------------------------- 1 | /* 2 | * promise-tracker - v2.0.0 - 2014-04-11 3 | * http://github.com/ajoslin/angular-promise-tracker 4 | * Created by Andy Joslin; Licensed under Public Domain 5 | */ 6 | 7 | (function() { 8 | 9 | angular.module('ajoslin.promise-tracker', []) 10 | 11 | .provider('promiseTracker', function() { 12 | var trackers = {}; 13 | 14 | this.$get = ['$q', '$timeout', function($q, $timeout) { 15 | function cancelTimeout(promise) { 16 | if (promise) { 17 | $timeout.cancel(promise); 18 | } 19 | } 20 | 21 | return function PromiseTracker(options) { 22 | //do new if user doesn't 23 | if (!(this instanceof PromiseTracker)) { 24 | return new PromiseTracker(options); 25 | } 26 | 27 | options = options || {}; 28 | 29 | //Array of promises being tracked 30 | var tracked = []; 31 | var self = this; 32 | 33 | //Allow an optional "minimum duration" that the tracker has to stay active for. 34 | var minDuration = options.minDuration; 35 | //Allow a delay that will stop the tracker from activating until that time is reached 36 | var activationDelay = options.activationDelay; 37 | 38 | var minDurationPromise; 39 | var activationDelayPromise; 40 | 41 | self.active = function() { 42 | //Even if we have a promise in our tracker, we aren't active until delay is elapsed 43 | if (activationDelayPromise) { 44 | return false; 45 | } 46 | return tracked.length > 0; 47 | }; 48 | 49 | self.tracking = function() { 50 | //Even if we aren't active, we could still have a promise in our tracker 51 | return tracked.length > 0; 52 | }; 53 | 54 | self.destroy = self.cancel = function() { 55 | minDurationPromise = cancelTimeout(minDurationPromise); 56 | activationDelayPromise = cancelTimeout(activationDelayPromise); 57 | for (var i=tracked.length-1; i>=0; i--) { 58 | tracked[i].resolve(); 59 | } 60 | tracked.length = 0; 61 | }; 62 | 63 | //Create a promise that will make our tracker active until it is resolved. 64 | // @return deferred - our deferred object that is being tracked 65 | self.createPromise = function() { 66 | var deferred = $q.defer(); 67 | tracked.push(deferred); 68 | 69 | //If the tracker was just inactive and this the first in the list of 70 | //promises, we reset our delay and minDuration 71 | //again. 72 | if (tracked.length === 1) { 73 | if (activationDelay) { 74 | activationDelayPromise = $timeout(function() { 75 | activationDelayPromise = cancelTimeout(activationDelayPromise); 76 | startMinDuration(); 77 | }, activationDelay); 78 | } else { 79 | startMinDuration(); 80 | } 81 | } 82 | 83 | deferred.promise.then(onDone(false), onDone(true)); 84 | 85 | return deferred; 86 | 87 | function startMinDuration() { 88 | if (minDuration) { 89 | minDurationPromise = $timeout(angular.noop, minDuration); 90 | } 91 | } 92 | 93 | //Create a callback for when this promise is done. It will remove our 94 | //tracked promise from the array if once minDuration is complete 95 | function onDone(isError) { 96 | return function(value) { 97 | (minDurationPromise || $q.when()).then(function() { 98 | var index = tracked.indexOf(deferred); 99 | tracked.splice(index, 1); 100 | 101 | //If this is the last promise, cleanup the timeouts 102 | //for activationDelay 103 | if (tracked.length === 0) { 104 | activationDelayPromise = cancelTimeout(activationDelayPromise); 105 | } 106 | }); 107 | }; 108 | } 109 | }; 110 | 111 | self.addPromise = function(promise) { 112 | var then = promise && (promise.then || promise.$then || 113 | (promise.$promise && promise.$promise.then)); 114 | if (!then) { 115 | throw new Error("promiseTracker#addPromise expects a promise object!"); 116 | } 117 | var deferred = self.createPromise(); 118 | 119 | //When given promise is done, resolve our created promise 120 | //Allow $then for angular-resource objects 121 | then(function success(value) { 122 | deferred.resolve(value); 123 | return value; 124 | }, function error(value) { 125 | deferred.reject(value); 126 | return $q.reject(value); 127 | }); 128 | 129 | return deferred; 130 | }; 131 | }; 132 | }]; 133 | }); 134 | 135 | }()); -------------------------------------------------------------------------------- /response.json: -------------------------------------------------------------------------------- 1 | angular.callbacks._0({ status : "OK", info : 'This is a dummy response used for this example. Normally this would be a server side application that validates submitted data and performs the email submission.' }) 2 | --------------------------------------------------------------------------------