Typed front-end met Angular 2

Sinds kort is de Developer Preview van Angular2 uitgebracht. Deze versie heeft enkele essentiële wijzigingen ten opzichte van Angular 1. Angular 2 is volledig geschreven in TypeScript en voldoet aan de Ecmascript 6 specificatie. Hoewel er nog geen gehele applicatie mee te maken is, omdat sommige specificaties nog niet uitgewerkt of nog aan verandering onderhevig zijn, is de richting waar het ontwikkelteam heen wil wel te zien.

Voordelen komen overigens niet alleen uit het gebruik van Angular, maar ook door het gebruik van TypeScript en Ecmascript 6. Het is allemaal nog niet af en binnen het Angular-ontwikkelteam is er niet altijd consensus. Hierdoor hebben enkele contributors het team al verlaten.

De werkwijze wordt daarentegen totaal verschillend dan bij Angular 1. Component based development en objectoriëntatie worden veel gemakkelijker, dit zal ik later verklaren. Andere zaken, zoals scopes en controllers zijn geheel komen te vervallen.

Component based

Angular 2 is volledig component based. Controllers en $scope komen ten opzichte van Angular 1 niet meer voor. Daarvoor in de plaats zijn components en directives gekomen. Components zijn directives met een template. Onderstaande code snippet, listing 1, geeft weer hoe een component is opgebouwd. Dit component is in HTML aan te roepen met de <angularComponent> tag , de naam van de selector, binnen de HTML.

Listing 1

Overigens moet je alle te gebruiken componenten via bootstrap kenbaar maken. Ook moet je ze importeren op de pagina.

 

Directives

De specificatie voor directives is aanzienlijk versimpeld. Deze is wel nog aan verandering onderhevig, nu nog niet alle functionaliteit is geïmplementeerd. Met de @Directive-annotatie kun je een directive declareren. Dit is te zien in Listing 2. Dit is slechts een beperkte set van de mogelijkheden. In het blok ‘host’ kun je standaard functies koppelen aan eigen implementaties.

 

Listing 2

Directives kunnen ook in componenten worden gebruikt. Dit geldt zowel voor eigen directives als voor gedefinieerde directives. Als de ‘NgFor’ als de ‘tooltip’ directive in een component worden gebruikt, worden deze in eerste instantie geïmporteerd en vervolgens kenbaar gemaakt in de directives property binnen de @View.

 

Dependency injection

Door het verbeterde dependency-injectiemodel van Angular2 zijn er meer mogelijkheden om component/ object based te werken. De dependency-injectie bestaat uit drie onderdelen:

  • De Injector die Apis beschikbaar stelt, waarmee je dependencies kunt injecteren;
  • Bindings waarmee dependencies een naam kunnen krijgen;
  • De daadwerkelijke dependencies waarmee het object wordt gegenereerd.

Op het moment dat een object wordt meegegeven binnen de constructor van het component, hoef je deze enkel via de viewInjector mee te geven, zoals in listing 3 te zien is. De objecten die tussen de rechte haken staan, kunnen vervolgens gebruikt worden om deze te injecteren.

Listing 3

Nog niet alles aan de dependency-injectie is geïmplementeerd. Er zijn wel wat extra annotaties die toegevoegde waarde hebben, zoals de @InjectPromise-annotatie. Hiermee kun je asynchroniteit bewerkstelligen en wordt het object pas geïnjecteerd als deze daadwerkelijk is aangemaakt. Er wordt specifiek een Promise-object geïnjecteerd. Met de @Optional-annotatie kun je een optionele waarde of library injecteren.

Een voorbeeld van dependency injection is de volgende declaratie:

Dependency Injection is hiërarchisch toe te passen waardoor er een gehele boomstructuur is te creëren. Er kan bijvoorbeeld een auto worden geïnjecteerd, waarvan de onderdelen ook zijn geïnjecteerd.

Een speciale toepassing van dependency injection is http. Door het gebruik van de httpInjectables die in het angular/http package zitten, kun je http-objecten injecteren. Hierop kunnen de standaard Rest-functies uitgevoerd worden. Dit gaat op de volgende manier als Rest service als een publieke test server is gebruikt.

http.get('http://jsonplaceholder.typicode.com/posts/1')

 

Wat is TypeScript en wat zijn de voordelen van Ecmascript 6

Ecmascript 6 kent classes, een typisch voorbeeld van een class is (listing 4):

 

Listing 4

In vorige versies van Ecmascript werd alles nog met een prototype gedefinieerd. Nu is alles meteen een class, wat het bijna leesbaar maakt als Java-code. Ecmascript 6 heeft ook volledige inheritance. Met super(parameters) roep je de constructor van de parent aan. Verder kun je static variabelen declareren.

Een ander voordeel is dat er standaard ondersteuning van Web Sockets is, waarmee je bijvoorbeeld eenvoudig een messaging service kunt bouwen. Door een socket te definiëren, zoals: var socket = new WebSocket('ws://localhost:3000'); kan hierop een onMessage() en emit worden aangeroepen. Je moet uiteraard dan wel een WebSocket-server definiëren.


TypeScript = ES6 + Types + Annotaties

TypeScript is eigenlijk van Microsoft en dat maakt de nieuwe Angular opeens ook populair bij .Net-ontwikkelaars. TypeScript is een vorm van Javascript die met classes wordt geprogrammeerd en vervolgens naar Javascript wordt gecompileerd. Het is open source. TypeScript bevat vele aspecten van objectoriëntatie, zoals inheritance en interfaces. Verder kent het generics en lambda’s.

Doordat Angular2 gebruik maakt van TypeScript is de gebouwde functionaliteit niet in grote mate afhankelijk van de functionaliteit die in Angular zit. Je kunt bijvoorbeeld rechtstreeks gebruik maken van de MongoDB-interface die al in TypeScript zit.

Uiteindelijk wordt in de browser geen TypeScript gebruikt. Je compileert de programmacode naar Javascript. Als de Javascript de Ecmascript 6 specificatie bevat, moet ook een extra plug-in gebruikt worden, omdat de browsers hiervoor nog niet geschikt zijn. Dit kun je oplossen door “Traceur” te gebruiken.

 

Generics

Typescript kent generics die vervolgens in de front-end zijn te gebruiken. Als voorbeeld gebruiken we een Male- en Female-class die beide afgeleid zijn van Person (Listing 5). Beiden kunnen Food bereiden, het resultaat is echter verschillend.

 

Listing 5

In het Angular-component moet je elke class die je gebruikt ook daadwerkelijk importeren. En als er een directive in de pagina wordt gebruikt, moet deze zowel geïmporteerd als gedeclareerd worden, zie bijvoorbeeld de NgFor in listing 6.

 

Listing 6

De ‘foods’ List kunnen we vervolgens presenteren in Angular, hiervoor is het volgende stukje html nodig:

Listing 7

De browser toont vervolgens een lijstje. Dit voorbeeld is nog relatief eenvoudig, later in het form-gedeelte zal duidelijk worden dat heel veel mogelijk is met gebruik van inheritance.

 

Lambda’s met TypeScript

In TypeScript zijn lambda’s beschikbaar, het onderstaande stuk code maakt van elke String in messageStrings een nieuwe message met deze string als inhoud. Het totaal wordt dan in de messages-lijst gepusht.

Listing 8

Ook hier heeft de http interface weer zijn eigen toepassing op lambda’s. De http get levert niet direct een bruikbaar object op, maar een RxJS Subject. Dit moet nu nog via de toRx() methode, maar deze zal later verdwijnen. Het RxJS Subject moet vervolgens gemapt worden naar een response Observable. Vervolgens wordt er een .subscribe aangeroepen op de Observable, waarmee het object kan worden geïnstantieerd.

 

Forms en validaties

Forms en validaties is een belangrijk aspect van front-end ontwikkeling. Binnen Angular 2 zijn hiervoor de FormBuilder en ControlGroup gedefinieerd. De ControlGroup bestaat uit een lijst van Control. In Listing 9 is te zien hoe je twee velden aan de ControlGroup toevoegt.

Listing 9

Het lege veld is de initiële waarde, maar hier kan uiteraard ook een waarde uit de database gebruikt worden. Vervolgens kun je dit op deze manier aangeroepen in de html.Listing 10

Nu is in de code de lijst met errors aan te roepen met:


 ‘<<this.orderForm.controls.naam.errors>>.

In het form zijn de fouten per element op te vragen, zoals in listing 10 is te zien. Er zijn ook ControlGroups binnen de ControlGroup te maken. Als je dit doet, kan er ook een validatie over velden worden gedefinieerd op Form-niveau. Deze validaties kun je dan aanroepen met:


orderForm.errors.

Elke validatie mag zelf geschreven worden. Ook de Controls zijn classen die uiteraard weer met een extend een eigen implementatie kunnen krijgen. Hiermee is ook op het gebied van FormControls een slimme library te maken met eigen functies. Het is dan niet nodig om alles opnieuw te definiëren. In combinatie met generics en inheritance is bijvoorbeeld een generieke datumcomponent te bedenken die een regel mee krijgt. De generieke regel is bijvoorbeeld dat de datum het juiste formaat heeft. De regel die met generics wordt toegevoegd, is dat de datum minimaal 18 jaar in het verleden moet liggen.

Ook het gedeelte met Forms ondergaat nog wijzigingen en de verwachting is dat nog meer standaard operaties worden meegeleverd.

 

Meer mogelijk?

Op dit moment is het nog niet zeker of alles gaat werken zoals is gespecificeerd. De richting is duidelijk, maar het kan nog voorkomen dat met een nieuwe minor release, de oude code niet meer werkt. Ook is het niet zo dat de voorbeelden altijd helpen, omdat de specificatie inmiddels alweer is aangepast. Omdat de front-end nu volledig uit componenten en directives bestaat, kunnen nu alle mogelijkheden van andere javascript libraries benut worden. Momenteel is nog niet alles geïmplementeerd in Angular2. Dat zal waarschijnlijk in de toekomst nog wel gebeuren. Het valt te verwachten dat gemakkelijk kan worden geïntegreerd met zowel Rest als andere communicatiemiddelen, zoals WebSockets en databases.

De combinatie Angular2 met TypeScript levert veel kansen voor objectgeoriënteerd programmeren in de front-end. Het declaratieve karakter maakt het allemaal veel overzichtelijker, helemaal omdat er geen $scope-objecten zijn. Wat wel een belangrijke rol gaat spelen, is het feit dat de beloofde functionaliteit echt gebouwd gaat worden. Nu zijn er nog teveel zaken die óf nog niet goed werken óf nog niet geïmplementeerd zijn. Het is ook meer een manier geworden om directives en componenten te maken. Daarnaast is heel gemakkelijk integratie mogelijk met andere frameworks. Het is ook niet meer een typisch Javascript-framework. Er wordt wel naar Javascript gecompileerd, maar de insteek is dat de taal waarin wordt geprogrammeerd vrij is als deze naar Javascript is te compileren.

Wat zeker is, is dat er nog heel veel gaat komen. Routing wordt bijvoorbeeld nog sterk aangepast. En als alle beloften worden waargemaakt, ziet het er veelbelovend uit!