Follow Us on Twitter

AngularJS voor dummies

Gepubliceerd in

September 2014 - AngularJS is een open-source webapplicatie framework, waarmee single page applicaties (SPA's) worden ontwikkeld. Het doel is om webapplicaties met model-view-controller (MVC) capaciteit te verrijken om zo zowel de ontwikkeling als het testen makkelijker te maken. SPA's staan in tegenstelling tot round-trip applicaties die statische HTML pagina's leveren afkomstig van de server. Bij round-trip applicaties wordt de browser gereduceerd tot een HTML-renderer, terwijl met AngularJS de browser verrijkt wordt met extra functionaliteit.

AngularJS wordt beheerd en onderhouden door Google en is sinds 2012 beschikbaar voor het grote publiek.

Waarom AngularJS

AngularJSIn de Java wereld zijn frameworks zoals Spring en Hibernate niet meer weg te denken. Er zullen weinig bedrijfs ICT projecten zijn waar geen enkel framework wordt gebruikt en men alleen puur Java code schrijft. In de front-end wereld (JavaScript) was er daarentegen tot voor kort geen sprake van noemenswaardige frameworks en bestonden er wel veelgebruikte libraries. Men kan stellen dat AngularJS eigenlijk het eerste echte volwassen JavaScript framework is. AngularJS kan binnen ieder project gebruikt worden waar services via REST zijn ontsloten.

Bij de ontwikkeling van AngularJS heeft men als filosofie gehanteerd dat het bouwen van user interfaces op declaratieve wijze moet plaatsvinden. Met AngularJS kan HTML worden uitgebreid met eigen vocabulair. De kracht van AngularJS schuilt verder in two-way data binding: wijzigingen in het model zijn zichtbaar in de view en wijzigingen in de view zijn meteen zichtbaar in het model. Dit maakt het mogelijk om de controller los te testen. Het resultaat zijn zeer expressieve, leesbare en snel te ontwikkelen applicaties.

Hoe zit het met JQuery?

AngularJS en JQuery hanteren een andere benadering bij applicatieontwikkeling. JQuery is ideaal voor manipulatie van de DOM van de browser om zo een rijke webapplicatie te ontwikkelen. AngularJS maakt optimaal gebruik van de browser in een "samen sterk" model. AngularJS maakt de browser krachtiger doordat semantiek kan worden toegevoegd. JQuery is een prachtig stuk gereedschap maar grote applicaties blijken dikwijls steeds moeilijker te onderhouden en uit te bouwen.

Dit gezegd hebbende is AngularJS wel gestoeld op de core functionaliteit van JQuery. In feite bevat AngularJS een lite versie van JQuery.

Voorbeeld Hello World

Laten we in standaard HTML hello world tonen:

<p>Hello World!</p>

Het resultaat is een rechttoe rechtaan, simpele en leesbare oplossing.

Laten we met behulp JQuery een hello world applicatie maken:

<p id="greeting"></p>

<script>
$function (a) {
   $('greeting').text('Hello World!');
});
</script>

Het resultaat is een minder rechttoe rechtaan en minder leesbare oplossing. Desondanks is vrij snel in te zien wat er gebeurt, via DOM manipulatie wordt de tekst Hello World! gezet.

Laten we het nu proberen met AngularJS MVC style:

<p ng:controller="GreetingCtrl">{{greeting}}</p>
<script> function GreetingCtrl(a) { this.greeting = 'Hello World!'; } </script>

Op het eerste oog lijkt deze oplossing even verbose als de JQuery oplossing. Er is echter een substantieel verschil, de te tonen tekst staat, gelijk het HTML voorbeeld, binnen de HTML tag <p>. We zien in dit geval echter een placeholder {{greeting}} welke de waarde krijgt binnen de controller GreetingCtrl. Vooralsnog is de pure HTML de winnaar in al z'n eenvoud. Het wordt natuurlijk allemaal anders als men meer dynamiek wil: bijvoorbeeld dat een multi-language Hello World gewenst is.

Voorbeeld een papegaai applicatie

We bouwen een applicatie waarbij de input in een tekstveld tijdens het intoetsen wordt gespiegeld op een andere plek op het scherm zoals hieronder.

Dit tik ik in       
Dit tik ik in

Laten we eerst eens zien hoe de JQuery oplossing eruit ziet.

<input id="veld" value="Jan Janssen">
<p id="groet"></p>

<script>
$(function (a) {
    var veld = $('veld');
    var groet = $('groet');
    
    function update(x) {
        groet.text('Hoi ' + veld.val() = '!');
    }

    update(x);

    veld.bind('keydown', function(a) {
        setTimeout(update, 0);
    });
});
</script>

Dit ziet er al een stuk complexer uit met veel procedurele code met voornamelijk DOM manipulatie.

Nu gaan we zien dat AngularJS echt uitblinkt in dit soort applicaties en de oplossing die AngularJS biedt ziet er als volgt uit:

<input id="naam" value='Jan Janssen'>
<p>Hello {{naam}}</p>

De eenvoud en leesbaarheid kan men gerust indrukwekkend noemen. Wat we hier zien is de kracht van two-way data binding. We kunnen ons voorstellen dat wanneer de omvang van een applicatie toeneemt de complexiteit toeneemt, waardoor de JQuery oplossing meer en meer ondoorzichtig gaat worden terwijl met AngularJS je grip op je applicatie kan houden.

Filters en repeaters

Een zeer handige standaard feature van AngularJS is de repeater directive waarmee lijsten eenvoudig kunnen worden getoond. Hieronder is een voorbeeld te vinden van het gebruik van een dergelijke repeater.

...
  <ul>
	<li ng-repeat="product in producten">
	  {{product.naam}}
	  <p>{{product.beschrijving}}</p>
	</li>
  </ul>
...

De lijst met producten is het model (zoals in AngularJS Model View Controller) en we hoeven geen ingewikkeld Javascript te schrijven om deze lijst uit lezen en vervolgens te presenteren op het scherm. Het is voldoende om declaratief, middels de ng-repeat directive, aan te geven dat we alle producten in de lijst getoond willen hebben, waarbij de placeholders bepalen welke velden dat zijn. Nu is het vaak zo dat men niet de complete lijsten (in ons voorbeeld alle producten) die afkomstig zijn van een REST service wil tonen en is men geïnteresseerd in een subset van de deze lijst. Hiertoe kunnen AngularJS-filters worden ingezet. Het mooie van filters is dat ze ook dynamisch zijn te bepalen. Laten we het voorgaande voorbeeld nemen en uitbreiden.

...
  Filter: <input ng-model="myfilter">

  <ul>
    <li ng-repeat="product in producten | filter:myfilter">
	  {{product.naam}}
       <p>{{product.beschrijving}}</p>
    </li>
  </ul>
...

Het initiële scherm zal er ongeveer uit zien zoals hieronder:

Filter:           
  • naam: Spinazie
    beschrijving: Ongewassen, herkomst Nederland.
  • naam: Elstar
    beschrijving: Fris en fruitig.
  • naam: Banaan
    beschrijving: herkomst Costa Rica.

Wanneer er in het filterveld een serie tekens worden ingevoerd dan zal AngularJS direct gaan filteren op de productlijst. In dit voorbeeld zal filtering toegepast worden op alle velden omdat een specifiek veld niet is aangegeven.

Voorbeeld:

Filter:  her      
  • naam: Spinazie
    beschrijving: Ongewassen, herkomst Nederland.
  • naam: Banaan
    beschrijving: herkomst Costa Rica.

Vaak wil men echter het filter toepassen op specifieke velden. Stel we willen het filter alleen toepassen op de beschrijving dan kunnen we het volgende doen:

...
  Filter: <input ng-model="myfilter.beschrijving">

  <ul>
    <li ng-repeat="product in producten | filter:myfilter:strict">
      {{product.naam}}
      <p>{{product.beschrijving}}</p>
    </li>
  </ul>
...

Als we dan "Banaan" invullen zal het resultaat een lege lijst zijn.

Filter:  Banaan 

Unit testen

Omdat in AngularJS de controller is losgekoppeld van de view kunnen we heuse unit tests gaan schrijven voor onze controller. De controller die gebruikt is in de voorgaande product voorbeelden is:

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

productApp.controller('ProductListCtrl', function ($scope) {
    $scope.producten = [
        {'naam': 'Spinazie',
            'beschrijving': 'Ongewassen, herkomst Nederland.'},
        {'naam': 'Elstar',
            'beschrijving': 'Fris en fruitig.'},
        {'naam': 'Banaan',
            'beschrijving': 'herkomst Costa Rica.'}
    ];
});

We zien dat in deze controller het model is opgebouwd tot een lijst van 3 producten. Een triviale doch typische unit test voor deze controller kan als volgt worden geschreven:

describe('ProductListCtrl', function(x){

it('We verwachten een lijst met 3 producten', function(x) {
  var scope = {},
      ctrl = new ProductListCtrl(scope);

  expect(scope.producten.length).toBe(3);
});
});

Naarmate de controller complexer wordt zullen uiteraard ook de unit testen in complexiteit toenemen.

Voorbeeld van een applicatie met backend

Javascript applicaties zijn uitermate geschikt om te koppelen met REST backend services en AngularJS applicaties zijn daarop geen uitzondering. Laten we de voorbeeldapplicatie uitbreiden met een koppeling naar een REST service met URL http://example.com/greet. Deze service groet ons op basis van de serverruimte temperatuur, bij meer dan 25 graden Celsius is de groet een warm "Bon dias" en bij temperaturen minder dan 25 graden Celsius is de groet een koele "Hallo".

Laten we in onze AngularJS applicatie hier gebruik van maken.

<div ng:controller="GreetingCtrl">
    <input name="naam">
    <button ng:click="groet(x)">Hallo</button>
    <p>{{groeten}}</p>
</div>

<script>
function GreetingCtrl($xhr) {
    var selfie = this;
    this.naam = 'Wereld';

    this.groet = function(a) {
        var url = 'http://example.com/greet';
                  url += '?callback=JSON_CALLBACK';
                  url  += '&naam=' + this.naam;
                  $xhr('JSON', url, function(code, response) {
                      selfie.groeten = response.groeten;
          });
}
}
</script>

We zien hier een aantal typische AngularJS features de revue passeren. Ten eerste de directives zoals ng:controller en ng:click. AngularJS komt met een omvangrijke en rijke set aan directives die de vaakst voorkomende scenarios in webapplicatieland ondersteunt. Directives ontsluiten de AngularJS core functionaliteit, zoals event handling, form validatie en templates. De directive ng:controller koppelt de controller aan de webpagina zodat het model (naam, groeten) gemanipuleerd kan worden. In dit voorbeeld wordt de getypte naam als request parameter meegeleverd aan de REST service op het moment dat op de button wordt geklikt (ng:click directive). De service op zijn beurt voegt een groet toe aan de naam en retourneert het resultaat in de response. De response wordt toegekend aan het model en direct zichtbaar op het scherm op de plek van de placeholder {{groeten}}.

Een tweede feature is dependency injection (DI). De lezers die uit de Java-wereld komen zijn waarschijnlijk zeer bekend met DI, zeker als men het Spring framework gebruikt. In dit voorbeeld zien we dat de controller gebruikmaakt van DI om XHR te benutten; XHR wordt geïnjecteerd in de controller met GreetingCtrl($xhr). Dit is de manier, voor AngularJS applicaties, waarop men allerlei services kan injecteren in de controller. Het voert te ver om hier XHR te beschrijven, kort gezegd het is een manier om met de webserver te communiceren.

Het resultaat, wanneer op de button is geklikt, is:

Bon dias Wereld

Blijkbaar heerst er een aangename temperatuur in de serverruimte.

Conclusie

AngularJS maakt het leven van de programmeur een stuk eenvoudiger bij het bouwen van een SPA. Door de eenvoud van AngularJS wordt de productiviteit verhoogd. Bovendien worden applicaties beter onderhoudbaar doordat de code leaner en leesbaarder wordt. Verdere voordelen van AngularJS zijn de testbaarheid van de applicaties en het gemak waarmee applicaties kunnen worden geport naar mobile devices. Binnen een paar jaar tijd heeft AngularJS bij het grote publiek een omvangrijke adaptatie bereikt. Het is bijna ondenkbaar dat een nieuw webapplicatieproject niet inzet op AngularJS.

Referenties

Waardering:
 
Tags:

Reacties

Nieuwe reactie inzenden

De inhoud van dit veld is privé en zal niet openbaar worden gemaakt.

Meer informatie over formaatmogelijkheden

CAPTCHA
Deze vraag is om te testen of u een persoon bent en om spam te voorkomen
Image CAPTCHA
Enter the characters shown in the image.