Monday, September 21, 2015

Keynote: AngularJS do the regular things.

Angular JS


Take a look on the previous article to refresh your memory
Angular JS Basics shornotes.

Angular Entities Overview

DMCE are base AngularEntities to work with:

  • Directives – HTML annotations that trigger Javascript behaviors.
  • Modules – Where our application components live.
  • Controllers – Where we add application behavior.
  • Expressions – How values get displayed within the page.

Directives

Directive it's just html annotation in some div that triggers corresponding js behavior.

<!-- directive ---- controller name -- alias to controller-->
<div ng-controller="StoreController as store">

Note: the alias is only visible only whithin this div.

Base directives

  • ng-app - specifies the Aplication module;
    <div ng-app = "myApp">
  • ng-controller - attach the Controller function to page;
    <div ng-controller="StoreController as store">
  • ng-show - defines whether to show div depends of some value;
    <button ng-show="store.product.canPurchase"> "Add to Cart" </button>
  • ng-hide - the opposite to ng-show - hides div if value or expression is true.
  • ng-repeat - iterate through the data list and creates the same divs as annotated one filled with the proper values for each list item.
    <li ng-repeat="product in store.products"> {{product.name}} </li>

More directives

  • ng-click - invokes specified controller method on click or automatically updates expression; <a href ng-click="panel.selectTab(1)" >Description</a>
  • ng-class - specifies the class to div. <li ng-class="{ active: tab.isSet(1) }"><a href ng-click="tab.setTab(1)">Description</a></li>
  • ng-src - rescue directive to load image after the Angular expression evaluation. <img ng-src="{{product.images[0].full}}"/>

Note: the Using Angular Expressions inside a src attribute will cause an error! <img src="{{product.images[0].full}}"/> …the browser tries to load the image before the Expression evaluates.

Forms directives

  • ng-init - allows us to evaluate an expression in the current scope (to set initial value in annotated scope)
    Note: it's better to do initialization inside controller.;
  • ng-model binds the form element value to the property;
    <select class="form-control" ng-model="review.stars" ng-options="stars for stars in [5,4,3,2,1]" title="Stars">
  • ng-options add some predefined options to choose; ng-options="stars for stars in [5,4,3,2,1]
  • ng-submit - allows us to call a function when a form is submitted. <form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewCtrl.addReview(product)>"

Note: Expressions define a 2-way Data Binding ... this means Expressions are re-evaluated when a property changes


Models

ng-model binds the form element value to the property.

  • keep the input info into some value into controller;
  • bind the html preview output to that value via ng-model directive;
  • annotate your form with ng-submit directiv to invoke controller function when form submitted;
  • save the submitted item to the storage;
  • reset the controller value to cleanup the input fields.

Submitting form example:

<!--  Review Form -->
<form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewCtrl.addReview(product)">
<!--  Live Preview -->
<blockquote>
  <strong>{{reviewCtrl.review.stars}} Stars</strong>
  {{reviewCtrl.review.body}}
  <cite class="clearfix">—{{reviewCtrl.review.author}}</cite>
</blockquote>
<!--  Review Form -->
<h4>Submit a Review</h4>
<fieldset class="form-group">
  <select ng-model="reviewCtrl.review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]" title="Stars">
   <option value="">Rate the Product</option>
  </select>
</fieldset>
<fieldset class="form-group">
  <textarea ng-model="reviewCtrl.review.body" class="form-control" 
   placeholder="Write a short review of the product..." title="Review">

Forms Validation

  • turn off default html validation via using novalidate;
  • mark required fields among your ng-models;
  • prints form validity for debug purposes <div> reviewForm is {{reviewForm.$valid}} </div>;
  • prevent the form submitting if the input isn't valid (otherwords submit only if valid); ng-submit="reviewForm.$valid && reviewCtrl.addReview(product)"
  • give the user a hint, why the form isn't valid;

Note: Angular marks your form with classes in the following way:

  • Source before typing email: <input name="author" . . . class="ng-pristine ng-invalid">
  • Source after typing, with invalid email: <input name="author". . . class="ng-dirty ng-invalid">
  • Source after typing, with valid email: <input name="author" . . . class="ng-dirty ng-valid">

So, u can highlight the field after start typing ng-dirty showing whether the field ng-valid or ng-invalid.

.ng-invalid.ng-dirty {border-color: #FA787E;} .ng-valid.ng-dirty {border-color: #78FA89;}

Angular has a build-in validations:

  • email: <input type="email" name="email">
  • url: <input type="url" name="homepage">
  • number: <input type="number" name="quantity min=1 max=10">

Filters

U can the pass the evaluated value of the expression to the filter and than output. Common template is {{ *data | filter:*options }}.

  • date: {{'1388123412323' | date:'MM/dd/yyyy @ h:mma'}}
    21/09/2015 @ 13:50AM
  • uppercase & lowercase: {{'amsterdam' | uppercase}} AMSTERDAM
  • limitTo: {{'My Description' | limitTo:7}} My Desc
  • orderBy: <li ng-repeat="product in store.products | orderBy:'-price'"> without the '-' products would list in ascending order

Base App Sample

myApp.js

(function() {
  var app = angular.module('gemStore', []);

  app.controller('StoreController', function(){
    this.products = gems;
  });

  app.controller('TabController', function(){
    this.tab = 1;

  this.setTab = function(newValue){
    this.tab = newValue;
  };

  this.isSet = function(tabName){
    return this.tab === tabName;
  };

  app.controller('GalleryController', function(){
    this.current = 0;
    this.setCurrent = function(newGallery){
    this.current = newGallery || 0;
  };
});

var gems = [
{
  name: 'Azurite',
  description: "Some gems have hidden qualities beyond their luster, beyond their   shine... Azurite is one of those gems.",
  shine: 8,
  price: 110.50,
  rarity: 7,
  color: '#CCC',
  faces: 14,
  images: [
    "images/gem-02.gif",
    "images/gem-05.gif",
    "images/gem-09.gif"
  ],
  reviews: [{
    stars: 5,
    body: "I love this gem!",
    author: "joe@example.org",
    createdOn: 1397490980837
  }, {
    stars: 1,
    body: "This gem sucks.",
    author: "tim@example.org",
    createdOn: 1397490980837
  }]
},...}];   
})();

index.html

<html ng-app="gemStore">
<head>
  <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
  <script type="text/javascript" src="angular.min.js"></script>
  <script type="text/javascript" src="app.js"></script>
</head>
<body class="list-group" ng-controller="StoreController as store">
  <header>
    <h1 class="text-center">Flatlander Crafted Gems</h1>
    <h2 class="text-center">– an Angular store –</h2>
  </header>
<div class="list-group-item" ng-repeat="product in store.products">
  <h3>
    {{product.name}}
    <em class="pull-right">{{product.price | currency}}</em>
  </h3>

  <!-- Image Gallery  -->
  <div class='gallery' ng-show="product.images.length" ng-controller="GalleryController as gallery">
    <img ng-src="{{product.images[gallery.current]}}" />
    <ul class="list-inline thumbs">
      <li class="thumbnail" ng-repeat="image in product.images">
        <img ng-src="{{image}}" />
      </li>
    </ul>
  </div>

  <section class="tab" ng-controller="TabController as panel">
    <ul class="nav nav-pills">
      <!--sets the li class to `active` if the 1st tab is set-->
      <li ng-class="{active: panel.isSet(1)}">
        <!--sets this (1st) tab as selected-->
        <blockquote><a href ng-click="panel.setTab(1)">Description</a></li>
      <li ng-class="{active: panel.isSet(2)}">
        <a href ng-click="panel.setTab(2)">Specs</a></li>
      <li ng-class="{active: panel.isSet(3)}">
        <a href ng-click="panel.setTab(3)">Reviews</a></li>
    </ul>
    <!--shows this div if the 1st tab is set-->
    <div ng-show="panel.isSet(1)">
      <h4>Description</h4>
      <blockquote>{{product.description}}</blockquote>
    </div>
    <div ng-show="panel.isSet(2)">
      <h4>Specs</h4>
      <blockquote>Shine: {{product.shine}}</blockquote>
    </div>
    <div ng-show="panel.isSet(3)">
      <h4>Reviews</h4>
      <blockquote></blockquote>
    </div>
  </section>
</div>
</body>
</html>

The most of examples are taken from AngularJS - ShapingUP course slides

next Topics


see Also


8 comments: