Validation in Angular 1.3 And other angular tidbits What is Angular? AngularJS is a structural framework for dynamic web apps. It lets you use HTML as your template language and lets you extend HTML's syntax to express your application's components clearly and succinctly. Angular's data binding and dependency injection eliminate much of the code you would otherwise have to write. And it all happens within the browser, making it an ideal partner with any server technology. Angular is what HTML would have been had it been designed for applications. HTML is a great declarative language for static documents. It does not contain much in the way of creating applications, and as a result building web applications is an exercise in what do I have to do to trick the browser into doing what I want? The impedance mismatch between dynamic applications and static documents is often solved with: a library - a collection of functions which are useful when writing web apps. Your code is in charge and it calls into the library when it sees fit. E.g., jQuery. frameworks - a particular implementation of a web application, where your code fills in the details. The framework is in charge and it calls into your code when it needs something app specific. E.g., durandal, ember, etc. Angular takes another approach. It attempts to minimize the impedance mismatch between document centric HTML and what an application needs by creating new HTML constructs. Angular teaches the browser new syntax through a construct we call directives. Examples include: Data binding, as in {{}}. DOM control structures for repeating/hiding DOM fragments. Support for forms and form validation. Attaching new behavior to DOM elements, such as DOM event handling. Grouping of HTML into reusable components. Developers Guide for AngularJS What is Angular (cont.)? Developed by Google Started in 2009 Google rebuilt DoubleClick in Angular, DoubleClick is premium version of AdSense Adoption is increasing Active project with large eco-system Supports modern browsers Angular Benefits Focuses on Separation of Concerns Is very opinionated (there is a right way…) Is very modularized and gives you a great way to organize your javascript code and break up work assignments to teams Much of the heavy lifting (Dom Manipulation, dependency injection) is done for you Allows you to create your own elements and attributes using directives Easily extensible Routing Embraces testing Angular application structure Modules are a container for the different parts of your app Scope is an object that refers to the application model. It is an execution context for expressions. Scopes are arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can watch expressions and propagate events. Controllers a Controller is a JavaScript constructor function that is used to augment the Angular Scope. Controllers are used to setup the initial state of the scope and add behavior to the scope Angular services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app. A filter formats the value of an expression for display to the user. At a high level, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children including validation. How do I use AngularJS? I build web business applications some intranet, some out in the wild. Backend is EF6, Web Api and one Odata app just for learning purposes For larger apps use BreezeJS (which I highly recommend) for client communication with the server and it’s server side components. Client side AngularJS, Bootstrap 3, Font Awesome, Angular-UI (jquery is required by Bootstrap, I rarely use) Sample application Technician Activity Tracking Requirements be able to have a technician enter the orders they worked on, the date worked, the hours for those orders, any issues encountered and any materials used. Be able to enter over the web, ideally enter from smartphone Application entirely developed in Visual Studio 2013 Backend Web Api and an Odata Controller just for fun, using Owin startup for configuration, no global.asax Client calls are all made using Angular resource module allowing interaction with RESTful service 3 controllers, one for the links at the top of the page, one for adding activities and one for viewing a grid of all activities 2 directives one for async validation of order number, one for validation of hours worked 1 factory which is just a façade over backend access 1 filter which is just a template function Validation What is demonstrated is only available in Angular 1.3 I highly recommend moving to 1.3 New directives ngMessages ngMessage These directives detect validation errors on the ngModel object and allow simpler communication of the validation issues Can be validation from either the standard HTML5 attributes and input types or custom directives including the ability to cross validate multiple controls. Can be used to prevent form submission The code HTML Page <div class="row col-md-7 "> <label>Work Date:</label> <div class="input-group"> <input type="text" id="workDate" name="workDate" class="form-control" datepicker-popup="{{format}}" ng-model="activity.workDate" min-date="minDate" maxdate="'2015-06-22'" datepicker-options="dateOptions" required close-text="Close" /> <span class="input-group-btn"> <button type="button" class="btn btn-default" ng-click="open($event)" tabindex="-1"><i class="glyphicon glyphicon-calendar"></i></button> </span> </div> <div ng-messages="activityForm.workDate.$error"> required</div> <div ng-message="required" class="alert alert-warning">Work Date is </div> </div> The code (continued) <div class="row col-md-7 "> <div class="form-group"> <label>Order Worked:</label> <input type="text" id="orderWorked" name="orderWorked" class="formcontrol" ng-model="activity.ordersWorked" required order-number-validator ng-modeloptions="{updateOn:'blur'}" ng-readonly="activityForm.orderWorked.$valid" /> </div> <div ng-messages="activityForm.orderWorked.$error"> required</div> <div ng-message="required" class="alert alert-warning">Order Number is <div ng-message="validOrderNumber" class="alert alert-warning">Not a valid order number</div> </div> <div ng-if="activityForm.orderWorked.$pending"> Checking Order Number... </div> </div> The directive .directive('orderNumberValidator', ['datacontext', function (datacontext) { return { require: 'ngModel', link: function ($scope, element, attrs, ngModel) { ngModel.$asyncValidators.validOrderNumber = function (modelValue, viewValue) { var val = modelValue || viewValue; return datacontext.validateOrderNumber(val); }; } }; }]); Comparative directive div class="form-group"> <label class="control-label" for="testMe">Test Me:</label> <input id="testMe" name="testMe" my-ui-validate="myTestFunction" ng-model-options="{updateOn:'blur'}" ng-model="model.item1" class="form-control"> </div> <div ng-messages="testForm.testMe.$error"> <div ng-message="validate"> Test string must be longer than four characters! </div> </div> .directive('myUiValidate', [function () { return { restrict: 'A', require: 'ngModel', link: function (scope, elm, attrs, ngModel) { var validateExpr = attrs.myUiValidate; if (!validateExpr){ return;} ngModel.$validators.validate = scope[validateExpr]; } }; }]) $scope.myTestFunction = function(value){ return value.length > 4 ; };