Monday, November 19, 2012

Angular JS: Form Validation

Basic form validation is already done for you in Angular JS... if you just know how to use it. Form validation in Angular is all done by directives, which means you just wire it up in markup, and you don't need to write a "validation function" in your controller to handle any of that dirty work.

Angular has wired up most form elements themselves to be directives, so <input type="email"/> will validate an email address and so on. Angular also looks for attributes like required  and handles them appropriately.

Let's have a look at some basic form validation in Angular:

The form

<form name="mainForm" ng-submit="sendForm()">
    <div>
      <label for="firstName">First Name</label>
      <input id="firstName" name="firstName" type="text" ng-model="person.firstName" required/>
      <span class="error" ng-show="mainForm.firstName.$error.required">required</span>
    </div>
    <div>
      <label for="lastName">Last Name</label>
      <input id="lastName" name="lastName" type="text" ng-model="person.lastName" required/>
      <span class="error" ng-show="mainForm.lastName.$error.required">required</span>
    </div>
    <div>
      <label for="email">Email</label>
      <input id="email" name="email" type="email" ng-model="person.email" required/>
      <span class="error" ng-show="mainForm.email.$error.required">required</span>
      <span class="error" ng-show="mainForm.email.$error.email">invalid email</span>
    </div>
    <div>
      <input type="checkbox" ng-model="agreedToTerms" 
        name="agreedToTerms" id="agreedToTerms" required/>
      <label for="agreedToTerms">I agree to the terms</label>
      <span class="error" ng-show="mainForm.agreedToTerms.$error.required">You must agree to the terms</span>
    </div>
    <div>
      <button type="submit">Send Form</button>
    </div>
  </form>


Here's a Plunker of the code at work:
NOTE: Plunker does not like Safari or IE, if you're seeing odd behavior in those browsers, there you go.



As you can see above, the validation information changes dynamically as you enter data, thanks to directives.

A few things to know about form validation in Angular:



  • ng-submit cannot be called until the entire form is $valid.
  • All validation and form data is actually stored in the scope under $scope['myFormName']. This is why you can write it out with Angular binding.
  • Access to validation information can be found via: $scope.nameOfForm.nameOfField. This means adding a name="" attribute to your inputs is very important.
  • Angular will automatically add CSS classes: ng-valid, ng-invalid, ng-dirty and ng-pristine to DOM elements to reflect their state.
There is also a lot of important information to be found in the documentation for the input directive.


EDIT: Additional information can be found in these blog entries:


Thursday, November 15, 2012

ALE Event Loop Framework - Added Promises

Did a little work tonight on ALE, my event loop framework for .NET. Decided to add a Promise implementation that leveraged the event loop. I fiddled with the usage a bit, so hopefully it's to people's liking.  I'm looking for any and all feedback on this addition.

For those of you that aren't familiar with promises, I did a blog entry a while ago about promises in JavaScript. This is pretty much the same idea. While in .NET there are WaitHandles and Tasks for synchronizing multiple asynchronous calls, I wanted something that would leverage the ALE's event loop engine that would do the same thing. So I decided to write a simple promise implementation.

Basic usage looks like this:

//create a single promise.
Promise.To((defer) => 
{
    try {
       //Do something here, and return a value
       defer.Resolve("complete");
    }catch{
       defer.Reject("this has been rejected.");
    }
}).Then((data) => 
{
    //When the above is complete, write the return value
    Console.WriteLine(data);
});

More advanced usage would be like so:

//a method to create a promise and run it.
public Promise Foo(string bar) {
    return Promise.To((defer) => 
    {
        Print(bar);
        defer.Resolve(bar);
    });
}

//using When to await the completion of multiple Promises.
Promise.When(Foo("One"), Foo("Two"), Foo("Three"))
   .Then((data) =>
    {
        Print("Complete");
    });

The above code would be used in situations where you might need to wait for multiple asynchronous calls before continuing. Using ALE's Promise class, you'll be able to do so without blocking a thread.

I'm really looking for any feedback/code-review anyone wants to do. So if you have the time please look it over.

Upcoming for ALE, I'm going to try to make most of the Asynchronous calls return a Promise, to enable more complex chaining of async calls. Also, possibly a method to re-execute a Promise.

Wednesday, November 7, 2012

Angular JS - Directive Basics

A while ago I posted some very basic information about AngularJS. There are a lot of really cool things to go over in Angular, but I think the most important thing to go over is probably directives. Directives are what tie everything together.


Where the rubber meets the road


Directives in angular are easily the most powerful and complicated peace to the puzzle. Directives are used to set up DOM manipulations, interactions between the DOM and the scope, and a great many other things. Examples of directives are all over the Angular core framework. ng-model, ng-clickng-repeat, ng-app are all examples of directives. Even the select, textarea and input tags have been extended as a directive. Directives can be used to set up JQuery plugins, do validation, create custom reusable controls.


Directives come in many different flavors


  • Elements - such as <my-directive>expression here</my-directive>
  • Attributes - such as <div my-directive="expression here"></div>
  • Classes - such as <div class="my-directive: expression here;"></div>
  • Comments - such as <!-- directive: my-directive expression here -->
All of the above examples could even be the exact same directives used differently.

The anatomy of a directive


Warning: the following example is contrived, and really silly. But I'm trying to illustrate the most commonly used pieces of a directive declaration.

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
});

//the following will declare a new directive that
// may be used like <my-directive name="foo"></my-directive>
// where foo is a property on a controller's scope.
app.directive('myDirective', function(){
  // The above name 'myDirective' will be parsed out as 'my-directive'
  // for in-markup uses.
  return {
    // restrict to an element (A = attribute, C = class, M = comment)
    // or any combination like 'EACM' or 'EC'
    restrict: 'E',
    scope: {
      name: '=name' // set the name on the directive's scope
                    // to the name attribute on the directive element.
    },
    //the template for the directive.
    template: '<div>Hello, {{name}} <button ng-click="reverseName()">Reverse</button></div>',
    //the controller for the directive
    controller: function($scope) {
      $scope.reverseName = function(){
        $scope.name = $scope.name.split('').reverse().join('');
      };
    },
    replace: true, //replace the directive element with the output of the template.
    //the link method does the work of setting the directive
    // up, things like bindings, jquery calls, etc are done in here
    link: function(scope, elem, attr) {
      // scope is the directive's scope,
      // elem is a jquery lite (or jquery full) object for the directive root element.
      // attr is a dictionary of attributes on the directive element.
      elem.bind('dblclick', function() {
        scope.name += '!';
        scope.$apply();
      });
    }
  };
});

The above directive is a crude example. It will output a "Hello, World" statement with a button to reverse the name with just the following markup: <my-directive name="name"></my-directive>, presuming the parent scope has a property name equal to "World". It will also set up a double-click event that will tack an exclamation point on the end of the name.

And here's my absurd directive in action:

 


Fears of "Custom HTML tags" are unfounded


Have no fear. Angular is not destroying your perfect markup. Angular is using them as placeholders, nothing more. The HTML spec itself even says that custom tags should be ignored. If you're using "replace: true" in your directives, it's all replaced by whatever HTML you put in the template anyhow. This is a common complaint I've heard about Angular, and it's just a bad reason not to at least try Angular. It's an incredibly fun and powerful tool.


Directive Tips & Gotchas


  • Use the existing directives to do your event binding if possible. Don't bind events with JQuery anymore, just stop it. Also, DO NOT do what I did in my example and create your own simple binding like "dblclick", there is already a directive
  • You can nest directives. A directive's template may contain other custom directives.
  • Put them in their own module. Generally, it's a good idea to organize your directives into their own module. This promotes reuse in other modules as well as a separation of concerns.
  • I've witnessed self-closing directive tags not function properly. Always use both the open and close tags for your element directives.

For more comprehensive information about directives, have a look here.