Vous cherchez la version en Français ? C’est par ici.

To discover Angular 2, several thousands of you have read our ebook Become a ninja with Angular 2 (thank you!). You may have noticed we spent a lot of time keeping it up to date with the tons of changes from the various betas and release candidates! All that for the price you decided, without DRM, in English and French, and with some ponies inside.

Thanks for all your feedbacks and amazing stories: it helps to know that this tremendous workload has been useful ;)

But we wanted to go further to share our experience in building modern JavaScript applications. An ebook is a great way to discover a topic, but it’s not enough to really master it. You have to experiment, test, read code and learn best practices. A great way is to follow a training, but we know that’s not always possible time-wise, location-wise, boss-wise or money-wise.

We came up with this idea to let you build a complete application step by step, an application that would be close to a real professional app (so… not a todo list…), but that would be fun enough (so… with ponies!). An application that would include components, services, routing, dependency injection, modules, http, websockets, lazy loading, authentication, forms, validations, performance tricks, production tricks, etc. And tests. Lots of tests. Because Angular 2 makes it easy to have a great code coverage and to build robust applications. This application is Ponyracer (take a look)!

Purple pony

The Pro Pack lets you build Ponyracer, step by step, with more than 30 exercises, each dedicated to a specific topic. For each step:

  • we provide all the unit tests to validate 100% of your code
  • we provide you all the necessary resources
  • we provide you the instructions (in English or in French)
  • you have to complete the exercises (with the help of our ebook and resources)
  • you can submit your score with a tool we wrote (it analyzes your code, checks the quality, measures the completeness and submit the result to our platform)
  • you can check the ‘state of the art’ solution we wrote for each exercise
  • you can go to the next step and continue, or skip to whatever exercise you want, as we provide the full project ready to use for each step.

See the Pro Pack in action:

Pro Pack demo

You can check the Pro Pack platform at angular2-exercises.ninja-squad.com and see the list of exercises by yourself.

We had nearly a hundred beta-testers over the past months, and they all have been ecstatic about it! As we regularly update the exercises (to keep up with the changes and new features in Angular 2) and add new ones, they often come back to see what changed, learn new tricks and how they can update their own projects.

The Pro Pack is really about gaining time and experience. It gives you an overview of everything you can do, how to test it and how to best implement it, in an always up-to-date fashion. If you complete the exercises, you will be able to tackle any project in Angular 2. I’m not saying that this will be an overnight process: you’ll have to spend several hours/days making your way through the Pro Pack. But we are really confident that what you’ll learn is way worth the money you’ll spend on the Pro Pack. The updates and new exercises will be free, of course.

Sounds interesting? It’s now available! Go buy it!

Oh and if you already bought the ebook, we have a nice discount for you! Just go to books.ninja-squad.com/discount to claim it! The offered discount will be slightly bigger than how much you gave, because we want to thank you for supporting us from the start.


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


Looking for the English version? It’s there.

Pour découvrir Angular 2, plusieurs milliers d’entre-vous se sont jetés sur notre ebook Devenez un Ninja avec Angular 2 (merci !). Vous avez probablement remarqué qu’on a consacré beaucoup de temps à le maintenir à jour avec tous les changements des différentes versions beta et release candidate. Et tout ça pour un prix de votre choix, sans DRM, en anglais et français, et avec des poneys en bonus !

Merci à tous pour vos retours et vos histoires incroyables : ça met du baume au cœur de savoir que cette conséquente charge de travail a été utile ;)

Mais on voulait aller plus loin pour partager notre expérience des applications JavaScript modernes. Un ebook est un bon moyen de découvrir un sujet, mais cela ne suffit pas à le maîtriser réellement.

Il faut expérimenter, tester, lire et écrire du code encore et encore pour apprendre les bonnes pratiques. Un moyen efficace est de suivre une formation, mais on sait que ce n’est pas toujours possible, que ce soit à cause des disponibilités, des localisations géographiques, de votre patron, ou du coût.

Alors on a eu cette idée de vous faire construire une application complète pas à pas, proche d’une application professionelle (donc pas une simple TODO list…), mais qui ne serait pas complètement rébarbative (d’où les poneys !). Une application qui contiendrait des composants, des services, du routage, de l’injection de dépendances, des modules, de l’HTTP, des WebSockets, du lazy loading, de l’authentification, des formulaires, de la validation, des astuces de performance, des astuces de mise en production, etc… Et des tests, des tonnes de tests. Parce qu’Angular 2 permet d’avoir une excellente couverture, et de construire des applications vraiment solides. Cette application est Ponyracer (jetez-y un œil) !

Poney

Notre Pack Pro te permet de construire PonyRacer, pas à pas, avec plus de 30 exercices, chacun étant consacré à un sujet précis.

  • On fournit tous les tests unitaires couvrant 100% de ton code.
  • On fournit toutes les ressources nécessaires.
  • On fournit toutes les instructions (en anglais ou français).
  • Vous complétez les exercices (avec l’aide de l’ebook et des ressources fournies).
  • Vous pouvez soumettre votre score via un outil que l’on a écrit (il analyse votre code, vérifie la qualité, mesure la complétude et soumet le résultat à notre plateforme).
  • Vous pouvez consulter la solution “état de l’art” qu’on a codée pour chaque exercise.
  • Vous pouvez continuer à l’étape suivante, ou sauter à l’exercice qui vous intéresse tout particulièrement : on vous fournit un projet fonctionnel pour débuter chaque étape.

Voici le Pack Pro en action :

Démo du Pack Pro Pack

Vous pouvez jeter un œil à la plateforme du Pack Pro sur angular2-exercises.ninja-squad.com et visualiser la liste des exercices prévus.

Près d’une centaine de beta-testeurs l’ont essayé sur les derniers mois, et ils nous on fait des retours très enthousiastes ! Comme on met fréquemment à jour les exercices (pour intégrer les changements et nouvelles fonctionnalités d’Angular 2), et comme on en ajoute de temps en temps, ils reviennent souvent pour voir ce qui a changé, apprendre de nouvelles actuces, et identifier comment impacter leurs propres projets.

Le Pack Pro permet de vraiment gagner du temps et de l’expérience. Il donne un aperçu de tout ce qu’on peut faire, comment le tester, et comment l’implémenter, dans le respect de l’état de l’art. Si vous complétez les exercices, vous serez prêt à vous attaquer à n’importe quel projet en Angular 2. Ne me faite pas dire que ça va être facile : il vous faudra plusieurs jours pour venir à bout de ce Pack Pro. Mais on sait que tout ce que vous apprendrez en chemin vaudra largement l’argent investi. Les mises à jour et les nouveaux exercices seront gratuits, évidemment.

Alors, intéressé ? Il est disponible dès maintenant !

Oh, et si vous avez déjà acheté l’ebook, on vous propose une chouette ristourne. Il vous suffit d’aller sur books.ninja-squad.com/discount pour la réclamer ! La remise sera légèrement plus importante que la somme que vous avez décidé de nous donner, parce qu’on est très fier que vous nous souteniez depuis le début, et qu’on veut vous en remercier chaleureusement.


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


Kotlin logo

I read about it, I saw several talks about it, I even played a little bit with it, but now I made one step further, and started using Kotlin on a small, but real project.

It’s only been one week, and it’s a brand new project, where the most experimented Kotlin programmer is… myself. So I’ve hit walls, learnt quite a few things, and will probably have more mature opinions about the language in the future. But I’d like to share my experience at this point anyway.

The good stuff

First of all, you shouldn’t be afraid. Learning a new language is always intimidating, but when you know Java already, Kotlin is easy to learn.

The documentation is top-notch; the tooling (IntelliJ, Gradle/Maven plugins) is almost as mature as for Java; the compatibility with Java is real, and you should thus be able to code real stuff in a few hours, even when starting from scratch.

The first thing that you enjoy is all the syntax candy that the language brings. No primitive types anymore, no semi-colons to separate statements (and it always works fine, unlike in some other languages), [] to access an element in a map, multi-line strings for your JSON or SQL, the elvis operator for null-safe access, foo.bar.baz instead of foo.getBar().getBaz(), etc. That doesn’t seem much, but it really makes the code more readable. Another cool stuff is the extensions methods, which allow to use plenty of utility methods that you would dream to have in Java: list.firstOrNull(), list.last(), string.toInt(), etc.

Something that bothers you for a few minutes, but then proves to be the greatest feature of Kotlin, is its null-safety. Every Kotlin type comes in two flavors: Foo and Foo?. A Foo cannot be null. If a method accepts a Foo, Kotlin won’t let you pass null to the method. If you receive a Foo as argument, you can be sure that it’s not null. With Java 8 came Optional, but Kotlin doesn’t really need it, since a method can return a Foo? to signal that it can return null. And Kotlin will force you to deal with the null case. That feature, alone, is a damn good reason to use Kotlin.

Another thing that I appreciate is the promotion of immutability and encapsulation. There are two ways to declare variables: var and val. val means final. Immutability is helped by making it the default, easy thing. Just use val. A List is immutable. If you want to mutate it, you need a MutableList. A MutableList is a List, so you can return a MutableList if your method has List as its returned type. And you don’t need to wrap it with Collections.unmodifiableList(): the caller won’t be able to add anything to the returned list, because it’s not mutable. The beauty of that mechanism is that it doesn’t work by reimplementing the whole Java collection framework. The actual implementations of those types are the standard collections that you already know and master.

Finally, the signal/noise ratio is much bigger in Kotlin than in Java. You can write a typical dumb DTO with 5 fields in a single line of code, using a data class. No fields, no getters, no setters, mutability of properties depending on the use of val or var. That is intimidating at first, because you can’t help but think that so much information and details are condensed in such a small piece of code: every character matters when you read it.

Another great thing that helps making your code clean, readable and immutable is the named parameters. Kotlin won’t force you to use them, but they are a good alternative to the builder pattern (or setters) that you typically use in Java when dealing with a large data structure. For example, instead of typing

val person = Person(1L, "Jean", "Lambert", 1975, 2000)

which is quite confusing (is Jean the first name or the last name? what are the two numbers at the end?)

you can type

val person = Person(id = 1L, firstName = "Jean", lastName = "Lambert", birthYear = 1975, score = 2000)

Now, suppose you want a copy of this person with an incremented score, you can do

val newPerson = person.copy(score = person.score + 1)

The copy method is generated for you by the compiler on data classes (but it’s quite easy to define it by yourself, too).

The pain points

Nothing is perfect in this world, and Kotlin is not either. The code that I have started writing is not a library. It’s a typical “enterprise” application using Spring. But the problem would be the same with a Java EE application.

Kotlin chose to apply one of Josh Bloch’s principles: Design and document for inheritance, or else prohibit it. What does that mean? It means that all classes and methods in Kotlin are final by default: inheritance is prohibited by default. To enable it, you must add the keyword open to your class, property or method. That is probably a good choice for libraries, but when it comes to “enterprise” applications, it becomes cumbersome. Spring and Java EE are both based on dynamic proxies, i.e. on dynamically generated classes that extend your classes. And unit-testing those classes with Mockito, for example, also relies on dynamically generated subclasses. The result is that Kotlin’s open is like Java’s public: it’s a modifier that you start adding everywhere because it is your default. (Note: this will probably be fixed)

Talking about Mockito, that’s another pain point. Let’s take an example:

when(mockUserDao.findByEmail(any())).thenReturn(null)

That code won’t work for two reasons:

  1. when is a keyword in Kotlin. That’s easy to circumvent though. You can use `when` instead. (that is cool by the way: my tests method all look like fun `should do this when that`() { ... })
  2. more problematic: Mockito.any() (and many other matchers) returns null, and findByEmail() takes a String as argument, not a String?. So that fails, too. Niek Haarman did a good job providing a mockito-kotlin project that helps avoiding these two problems, but unfortunately, it’s based on the latest Mockito beta version, which is not the one required by Spring Boot. It was easy enough to adapt, but still, it’s a pain point.

Finally, Kotlin chose to adopt the Pascal way of declaring variables and functions: instead of typing the type first and the name after (Foo foo, Foo makeFoo()) the name comes first and the type after, even if inferred most of the time (var foo: Foo, fun makeFoo(): Foo). Note for the young hipsters reading that blog: Pascal was a very popular language back in the days, that was used by many schools to teach programming. That is a minor thing, but when you are used to the Java/JavaScript/C way for 20 years, your brain has a hard time doing it the other way. And I haven’t found a way to make the IDE help me with code completion. For example, when I have to declare a field FooBarBaz fooBarBaz in Java, I can just type FBB TAB Space f TAB, and the IDE autocompletes for me. But I haven’t found the way to do the same in Kotlin where the property must be defined as val fooBarBaz: FooBarBaz.

Mixed feelings

There are other stuff in Kotlin that I find a little bit disturbing, but maybe just because I’m not used to it yet, or because the language will improve them later. Those include:

  • companion objects instead of static fields and methods (I haven’t seen the real gain yet)
  • hard to remember syntax for creating anonymous class instances;
  • the lack of method references on objects, but that will come in a future version;
  • top-level variables and functions (I haven’t seen the real gain over static variables and methods);
  • the lack of package-level visibility. It seems to be circumvented by declaring multiple classes in the same file, but I find it ugly: it’s hard to find your classes if you’re not using an IDE.
  • function types instead of named functional interfaces (I find them hard to read, especially when defining generic higher-order functions: Predicate<T> is clearer to me than (T) -> Boolean)
  • the fact that SAM Java interfaces can be written lambda-style, but not SAM Kotlin interfaces
  • arrays that are invariant (unlike Java, which is good), but which still don’t behave like lists when it comes to equality (you still can’t use == to compare arrays just like you would do for lists)
  • the short syntax for function (fun foo() = bar()) which looks like unnecessary additional syntax to me
  • some other stuff that I can’t remember :-).

Conclusion

After just one week, although the language is not perfect yet, I definitely like it a lot. I would use it over Java 8, and even more over Java 6 or 7. Kotlin runs on Java 6, so if you’re doing Android development, you should really consider Kotlin as a much better alternative. If you’re using Java 8, like I do, you should still really consider it, for all the good stuff this article started with.

Kotlin has also been announced as the future language of choice for Gradle, and I can’t wait to be able to use it for my Gradle builds, and benefit for Gradle and code completion in the IDE.

Are you already using Kotlin? I’d love to know what you think about it. Comments welcome!


JB Nizet


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


2016-05-11

Chez Ninja Squad, on aime beaucoup Laurent “@on_code” Victorino. Comme l’essentiel du reste du Monde d’ailleurs, car Laurent est un homme fondamentalement aimable.

Laurent est aussi développeur, comme nous. Pourtant, nous ne sommes pas du même monde : dans sa bouche, nous sommes du monde des “cravateux”, ces développeurs qui font des applications de gestion pour les entreprises. Et lui, il développe des jeux vidéo indie, au sein du studio qu’il a fondé, Monkey Moon, après avoir travaillé sur des AAA chez des grands éditeurs. Et dans son domaine, à défaut de devenir notablement riche, il s’est forgé une solide réputation.

Son outil de prédilection est Unity, un moteur de jeux 2D ou 3D, qui se veut très accessible. Et à chaque fois que nous nous retrouvions autour d’un burger pour refaire le monde, il ne cessait de nous inviter à venir s’essayer à la création de jeux. On lui répondait qu’on n’avait pas cette capacité, il nous rétorquait que c’était beaucoup plus facile qu’on ne l’imaginait. On a du mal à le croire, pourtant il enseigne largement la création de jeux, dans les écoles spécialisées comme pour un jeune public dans les musées : il doit avoir éprouvé ce qu’il raconte. Il était même venu présenter son travail et initier des débutants à Mix-IT, une conférence chère à notre cœur, car organisée par certains ninjas.

Alors pourquoi ne pas s’essayer au développement de jeu. Et plutôt que profiter égoïstement de notre proximité avec ce généreux grand homme, on s’est dit que cela pourrait vous intéresser aussi, soit parce que vous aimez le jeu vidéo depuis que vous jouiez à la NES les yeux collés à votre écran cathodique assis sur le tapis du salon, soit pour se confronter à un univers de développement très éloigné de nos petits problèmes de transaction en BDD et de formulaires web.

Videogames are for idiots - Monkey Moon

Une vingtaine de personnes sont donc cordialement invitées, aux frais de la princesse des ninjas, à un atelier d’initiation au développement de jeu vidéo avec Unity, le vendredi 20 mai 2016 après-midi. Cela se passera à La Cordée Liberté.

Quelques conditions :

  • savoir coder, quelque soit le langage. Nous utiliserons C# sous Unity, mais il comprend aussi le JS ;
  • être disponible le vendredi 20 mai après-midi sur Lyon ;
  • posséder un ordinateur portable sur lequel peut s’installer Unity : Mac ou Windows ;
  • venir avec son ordinateur portable et Unity ;
  • être sympathique.

Pour vous inscrire, il vous faut remplir ce formulaire.
On vous confirmera rapidement si vous faites partie des heureux premiers élus.

À très vite !


Cyril Lacôte


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


AngularJS 1.5.x has been out for a few weeks now but, despite tracking the changelog, I missed a change that this version introduces: one-way binding in directives.

When you need to pass an argument to a directive, there are 3 ways of doing it:

  • using @, to pass a string value. You can pass a dynamic string by using mustaches:

    <my-directive name="{{ thePony.name }}"></my-directive>
    
  • using =, to pass an expression of any type:

    <my-directive pony="thePony"></my-directive>
    
  • using &, to pass some code that the directive is free to execute when it needs to:

    <my-directive on-selection="setSelectedPony(thePony)"></my-directive>`
    

The second way does more than that, though: it establishes a two-way binding between the directive scope’s pony and the controller scope’s thePony:

  • assigning a new value to thePony in the controller scope will assign a new value to pony in the directive scope;
  • assigning a new value to pony in the directive scope will assign a new value to thePony in the controller scope;
  • changing an attribute (the color, for example) of thePony in the controller scope, will change the attribute in pony, in the directive scope;
  • changing an attribute (the color, for example) of pony in the directive scope, will change the attribute in thePony, in the controller scope.

Most of the time, the directive needs to get information from the controller, but doesn’t need to change that information. The second bullet point above is something we don’t really need. And this two-way binding has a certain cost.

Since AngularJS 1.5, it’s now possible to bind a value one-way, using <:

  • assigning a new value to thePony in the controller scope will assign a new value to pony in the directive scope;
  • assigning a new value to pony in the directive scope will not assign a new value to thePony in the controller scope. Don’t do that, it’s nasty;
  • changing an attribute (the color, for example) of thePony in the controller scope, will change the attribute in pony, in the directive scope: they both reference the same object;
  • changing an attribute (the color, for example) of pony in the directive scope, will change the attribute in thePony, in the controller scope: they both reference the same object.

As far as I know, this has been done for several reasons:

  • it aligns more closely with Angular2, where one-way binding is the norm;
  • it allows to avoid making a copy of the object passed as argument to the directive;
  • it allows creating a single watcher in the controller scope, that watches by identity instead of equality, making it faster.

More details are available in the documentation. You can also experiment with a little plunkr I wrote to show the difference of behavior between the two.

Enjoy!


JB Nizet


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


Cette semaine au lieu d’un Ninja Tip, nous te proposons un article sur TypeScript, extrait de notre ebook sur Angular 2 et traduction en français d’un précédent post.

Tu sais probablement que les applications Angular 2 peuvent être écrites en ES5, ES6 (voir nos posts à ce propos), ou TypeScript. Et tu te demandes peut-être qu’est-ce que TypeScript, et ce qu’il apporte de plus.

JavaScript est dynamiquement typé. Tu peux donc faire des trucs comme :

let pony = 'Rainbow Dash';
pony = 2;

Et ça fonctionne. Ça offre pleins de possibilités : tu peux ainsi passer n’importe quel objet à une fonction, tant que cet objet a les propriétés requises par la fonction :

let pony = { name: 'Rainbow Dash', color: 'blue' };
let horse = { speed: 40, color: 'black' };
let printColor = animal => console.log(animal.color);

Cette nature dynamique est formidable, mais elle est aussi un handicap dans certains cas, comparée à d’autres langages plus fortement typés. Le cas le plus évident est quand tu dois appeler une fonction inconnue d’une autre API en JS : tu dois lire la documentation (ou pire le code de la fonction) pour deviner à quoi doivent ressembler les paramètres. Dans notre exemple précédent, la méthode printColor attend un paramètre avec une propriété color, mais encore faut-il le savoir. Et c’est encore plus difficile dans notre travail quotidien, où on multiplie les utilisations de bibliothèques et services développés par d’autres.

Un des co-fondateurs de Ninja Squad se plaint souvent du manque de type en JS, et déclare qu’il n’est pas aussi productif, et qu’il ne produit pas du code aussi bon qu’il le ferait dans un environnement plus statiquement typé. Et il n’a pas entièrement tort, même s’il trolle aussi par plaisir ! Sans les informations de type, les IDEs n’ont aucun indice pour savoir si tu écris quelque chose de faux, et les outils ne peuvent pas t’aider à trouver des bugs dans ton code. Bien sûr, nos applications sont testées, et Angular a toujours facilité les tests, mais c’est pratiquement impossible d’avoir une parfaite couverture de tests.

Cela nous amène au sujet de la maintenabilité. Le code JS peut être difficile à maintenir, malgré les tests et la documentation. Refactoriser une grosse application JS n’est pas chose aisée, comparativement à ce qui peut être fait dans des langages statiquement typés. La maintenabilité est un sujet important, et les types aident les outils comme les développeurs à éviter les erreurs lors de l’écriture et la modification de code. Google a toujours été enclin à proposer des solutions dans cette direction : c’est compréhensible, étant donné qu’ils gèrent des applications parmi les plus grosses du monde, avec GMail, Google apps, Maps… Alors ils ont essayé plusieurs approches pour améliorer la maintenablité des applications front-end : GWT, Google Closure, Dart… Elles devaient toutes faciliter l’écriture de grosses applications web.

Avec Angular 2, l’équipe Google voulait nous aider à écrire du meilleur JS, en ajoutant des informations de type à notre code. Ce n’est pas un concept nouveau pour JS, c’était même le sujet de la spécification ECMASCRIPT 4, qui a été abandonnée. Au départ ils annoncèrent AtScript, un sur-ensemble d’ES6 avec des annotations (des annotations de type et d’autres). Ils annoncèrent ensuite le support de TypeScript, le langage de Microsoft, avec des annotations de type additionnelles. Et enfin, quelques mois plus tard, l’équipe TypeScript annonçait, après un travail étroit avec l’équipe de Google, que la nouvelle version du langage (1.5) aurait toutes les nouvelles fonctionnalités d’AtScript. L’équipe Angular déclara alors qu’AtScript était officiellement abandonné, et que TypeScript était désormais la meilleure façon d’écrire des applications Angular 2 !

Hello TypeScript

Je pense que c’était la meilleure chose à faire pour plusieurs raisons. D’abord, personne n’a vraiment envie d’apprendre une nouvelle extension de langage. Et TypeScript existait déjà, avec une communauté et un écosystème actifs. Je ne l’avais jamais vraiment utilisé avant Angular 2, mais j’en avais entendu du bien, de personnes différentes. TypeScript est un projet de Microsoft, mais ce n’est pas le Microsoft de l’ère Ballmer et Gates. C’est le Microsoft de Nadella, celui qui s’ouvre à la communauté, et donc, à l’open-source. Google en a conscience, et c’est tout à leur avantage de contribuer à un projet existant, plutôt que de maintenir le leur. Le framework TypeScript gagnera de son côté en visibilité : win-win comme dirait ton manager.

Mais la raison principale de parier sur TypeScript est le système de types qu’il offre. C’est un système optionnel qui vient t’aider sans t’entraver. De fait, après avoir codé quelque temps avec, il s’est fait complètement oublier : tu peux faire des applications Angular 2 en utilisant les trucs de TypeScript les plus utiles et en ignorant tout le reste avec du pur JavaScript (ES6 dans mon cas).

Si tu te demandes “mais pourquoi avoir du code fortement typé dans une application Angular 2 ?”, prenons un exemple. Angular 1 et 2 ont été construits sur le puissant concept d’injection de dépendance. Tu le connais déjà peut-être, parce que c’est un design pattern classique, utilisé dans beaucoup de frameworks et langages, et notamment AngularJS 1.x comme je le disais.

Un exemple concret d’injection de dépendance

Pour synthétiser ce qu’est l’injection de dépendance, prenons un composant d’une application, disons RaceList, permettant d’accéder à la liste des courses que le service RaceService peut retourner. Tu peux écrire RaceList comme ça :

class RaceList {
  constructor() {
    this.raceService = new RaceService();
    // let's say that list() returns a promise
    this.raceService.list()
    // we store the races returned into a member of `RaceList`
      .then(races => this.races = races);
      // arrow functions, FTW!
  }
}

Mais ce code a plusieurs défauts. L’un d’eux est la testabilité : c’est compliqué de remplacer raceService par un faux service (un bouchon, un mock), pour tester notre composant.

Si nous utilisons le pattern d’injection de dépendance (Dependency Injection, DI), nous déléguons la création de RaceService à un framework, lui réclamant simplement une instance. Le framework est ainsi en charge de la création de la dépendance, et il peut nous “l’injecter”, par exemple dans le constructeur :

class RaceList {
  constructor(raceService) {
    this.raceService = raceService;
    this.raceService.list()
      .then(races => this.races = races);
  }
}

Désormais, quand on teste cette classe, on peut facilement passer un faux service au constructeur :

let fakeService = {
  list: () => {
    // returns a fake promise
  }
};
let raceList = new RaceList(fakeService);
// now we are sure that the race list
// is the one we want for the test

Mais comment le framework sait-il quel composant injecter dans le constructeur ? Bonne question ! AngularJS 1.x se basait sur le nom du paramètre, mais cela a une sérieuse limitation : la minification du code va changer le nom du paramètre. Pour contourner ce problème, tu pouvais utiliser la notation à base de tableau, ou ajouter des métadonnées à la classe :

RaceList.$inject = ['RaceService'];

Il nous fallait donc ajouter des métadonnées pour que le framework comprenne ce qu’il fallait injecter dans nos classes. Et c’est exactement ce que proposent les annotations de type : une métadonnée donnant un indice nécessaire au framework pour réaliser la bonne injection. En Angular 2, avec TypeScript, voilà à quoi pourrait ressembler notre composant RaceList :

class RaceList {
  raceService: RaceService;
  races: Array<string>;

  constructor(raceService: RaceService) {
    // the interesting part is `: RaceService`
    this.raceService = raceService;
    this.raceService.list()
      .then(races => this.races = races);
  }
}

Maintenant l’injection peut se faire sans ambiguité ! Tu n’es pas obligé d’utiliser TypeScript en Angular 2, mais clairement ton code sera plus élégant avec. Tu peux toujours faire la même chose en pur ES6 ou ES5, mais tu devras ajouter manuellement des métadonnées d’une autre façon.

Angular 2 est clairement construit pour tirer parti d’ES6 et TS 1.5+, et rendre notre vie de développeur plus facile en l’utilisant. Et l’équipe Angular a envie de soumettre le système de type au comité de standardisation, donc peut-être qu’un jour il sera normal d’avoir de vrais types en JS.

Voici donc un des chapitres de notre ebook sur Angular 2, si celui-là vous a plu, n’hésitez pas à lire les autres !


Cédric Exbrayat


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


Comme tout le monde, vous développez des applications de gestion (ça se saurait si on pouvait gagner sa vie en développant des jeux vidéo). Et comme vous n’êtes pas très fort en front design, vous bénissez les framework CSS comme Bootstrap, qui vous permettent de capitaliser plein de bonnes pratiques qui vous dépassent, et d’avoir un rendu plutôt joli sans trop réfléchir. Ça donne un rendu certes pas très original (Bootstrap est le nouveau moche disent certains), mais ça contribue grandement à votre productivité. Ne culpabilisez pas, j’en suis là aussi (on doit être de la même génération de vieux).

Vous voilà donc à devoir coder votre formulaire de login en Angular 2 et Bootstrap. Le template HTML, s’il utilise un formulaire Angular 2 piloté par le modèle plutôt que piloté par le template, pourrait ressembler à cela :

<form (ngSubmit)="login()" [ngFormModel]="loginForm">

  <div class="form-group">
    <label for="username">Login</label>
    <input id="username" type="text"
           class="form-control" ngControl="username" required>
  </div>

  <div class="form-group">
    <label for="password">Mot de passe</label>
    <input id="password" type="password"
           class="form-control" ngControl="password" required>
  </div>

  <button type="submit" class="btn btn-primary">
    Me connecter
  </button>
</form>

Bravo, vous n’avez pas oublié l’attribut required sur les deux éléments <input>, car ces deux champs sont bien obligatoires. Les navigateurs modernes devraient même empêcher de soumettre le formulaire si ces deux champs ne sont pas saisis. Mais un peu de feedback utilisateur ne ferait pas de mal pour l’ergonomie.

Alors vous voulez ajouter un petit texte d’aide, pour préciser que ces champs sont obligatoires. Bootstrap propose une classe .help-block, dont c’est justement le propos :

<div class="form-group">
  <label for="password">Mot de passe</label>
  <input id="password" type="password"
         class="form-control" ngControl="password" required>
  <span class="help-block">
    Le mot de passe est obligatoire
  </span>
</div>

Mais dès que ce formulaire est affiché, ces messages sauteront aux yeux de l’utilisateur, alors qu’il n’a encore rien saisi. Chez Ninja Squad on aime bien que les messages ne s’affichent qu’une fois que l’utilisateur a commencé à saisir. Vous pouvez alors tirer bénéfice des possibilités surnaturelles de validation offertes par un formulaire Angular 2 :

<div class="form-group"
     [ngClass]="{
        'has-error': password.dirty
                     && !password.valid }">
  <label for="password">Mot de passe</label>
  <input id="password" type="password"
         class="form-control" ngControl="password">
  <span class="help-block"
        [hidden]="password.pristine
                  || !password.hasError('required')">
    Le mot de passe est obligatoire
  </span>
</div>

<button type="submit" class="btn btn-primary" [disabled]="!loginForm.valid">
  Me connecter
</button>

Qu’avons-nous mis en œuvre ici ?

  • On applique grâce à la directive ngClass la classe Bootstrap .has-error sur la div.form-group si le champ password :
    1. est dirty, c’est à dire modifié par l’utilisateur ;
    2. a une erreur de validation.
  • On n’active le bouton de soumission que si le formulaire est valide, grâce à la propriété disabled du DOM.
  • On masque le span.help-block grâce à l’attribut HTML 5 global hidden, si :
    1. le champ est pristine, c’est à dire vierge de toute modification par l’utilisateur (l’état lors de l’affichage initial) ;
    2. ou si le champ n’a aucune erreur 'required' de validation.

Plutôt cool. Sauf que… ça ne marche pas complètement. En l’état, le span.help-block sera toujours affiché, même quand le champ est vierge, même quand il n’a pas d’erreur.

Ce n’est pas une erreur dans la condition. Ce n’est pas un bug de votre navigateur qui ne supporterait pas cet attribut HTML 5. Ce n’est pas non plus un bug de binding d’Angular 2 sur cet attribut HTML 5. Ce problème m’a coûté quelques bonnes minutes de sueurs froides. Ce pourquoi je voulais vous partager ce ninja tip, aussi anecdotique soit-il.

En fait, le problème se situe dans le comportement de l’attribut HTML 5 global hidden, et les styles apportés par la classe Bootstrap .help-block. La documentation de hidden explique :

changing the value of the CSS display property on an element with the hidden attribute overrides the behavior.

Ce qui signifie pour les auvergnats :

modifier la valeur de la propriété CSS display sur un élement avec l’attribut hidden surcharge son comportement.

Et en l’occurrence, la classe help-block apporte entre autre le style display: block; (source)…

Voilà pourquoi votre texte d’aide à l’utilisateur apparaît toujours alors que votre utilisation de la validation Angular 2 est parfaite.

OK, cool. Et maintenant on fait quoi ? Et bien soit on enlève la classe help-block (mais on perd le style apporté), soit on réécrit son template pour ne plus faire du binding sur l’attribut hidden. Et la directive ngIf arrive alors à la rescousse :

<span class="help-block"
      *ngIf="password.dirty
             && password.hasError('required')">
  Password is required
</span>

Et voilà ! Il nous a fallu inverser la condition initialement placée dans [hidden]="..." (mais c’est de l’algèbre de Boole niveau CP), et on a remplacé le test de pristine par un test de dirty, qui sont les opposés.

Mise à jour du 12/05/2016 : solution alternative.

Thomas Queste nous suggère dans les commentaires de la version anglaise de cet article une autre solution vue sur StackOverflow : placer le message d’erreur dans son propre span à l’intérieur du span.help-block.

Merci d’avoir suivi ce long cheminement pour me permettre de vous expliquer cette anecdote, je me sens mieux d’avoir pu vider mon sac. Vous pouvez reprendre une activité normale (comme la lecture de notre ebook sur Angular 2 par exemple).


Cyril Lacôte


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


Like everybody, you code enterprise software for a living (because everybody know you can’t make a living by building videogames). And as you’re not very good at designing web pages, you enjoy using CSS frameworks like Bootstrap, providing best practices for free, and a nice design without thinking about it. Alright, your websites are not very original (some say Bootstrap is the new ugly), but thanks to it you’re productive. Don’t blame yourself, I do exactly the same (maybe we’re too old for this internet shit).

So you get to build this login form with Angular 2 and Bootstrap. The HTML template, if using a model-driven form instead of a template-driven one, may look like:

<form (ngSubmit)="login()" [ngFormModel]="loginForm">

  <div class="form-group">
    <label for="username">Login</label>
    <input id="username" type="text"
           class="form-control" ngControl="username" required>
  </div>

  <div class="form-group">
    <label for="password">Password</label>
    <input id="password" type="password"
           class="form-control" ngControl="password" required>
  </div>

  <button type="submit" class="btn btn-primary">
    Sign me in
  </button>
</form>

Congratulations, you’ve even thought about adding the required on both <input> elements. Modern browsers should prevent from submitting this form with empty inputs. But some feedback wouldn’t hurt the user experience.

So you’re trying to add some help text, to explain that these fields are mandatory. Bootstrap even has an .help-block class, which purpose is exactly this:

<div class="form-group">
  <label for="password">Password</label>
  <input id="password" type="password"
         class="form-control" ngControl="password" required>
  <span class="help-block">
    Password is required
  </span>
</div>

But as soon as this form is displayed, this help text is displayed, even if the user has not typed anything yet. At Ninja Squad, we like to have those hints and error messages be displayed only when the user has started to input something, to keep a clean form when entering the page. You may then leverage the validation capabilities of a super-charged Angular 2 form:

<div class="form-group"
     [ngClass]="{
        'has-error': password.dirty
                     && !password.valid }">
  <label for="password">Password</label>
  <input id="password" type="password"
         class="form-control" ngControl="password">
  <span class="help-block"
        [hidden]="password.pristine
                  || !password.hasError('required')">
    Password is required
  </span>
</div>

<button type="submit" class="btn btn-primary" [disabled]="!loginForm.valid">
  Sign me in
</button>

What are we doing here?

  • We apply, thanks to the ngClass directive, the Bootstrap’s .has-error class on div.form-group if the password field:
    1. is dirty, i.e. modified by the user;
    2. has a validation error.
  • We enable the submit button only if the form is globally valid, thanks to the disabled DOM property.
  • We hide the span.help-block element thanks to the HTML 5 hidden global attribute, if:
    1. the input is pristine, i.e. without any modification from user (the initial state);
    2. or if the field has no 'required' validation error.

Cool! Unless… that does not really work. The span.help-block will always be displayed, even with a pristine input, even without any validation error.

That is not an error in the condition. That is not your browser not implementing this HTML 5 hidden attribute. That is also not an Angular 2 binding bug on this HTML 5 attribute. This issue gave me some cold sweat, that’s why I wanted to share this ninja tip with you, be it very anecdotic.

The issue is between the HTML 5 hidden global attribute behavior, and the styles brought by Bootstrap’s .help-block class. The hidden documentation explains :

changing the value of the CSS display property on an element with the hidden attribute overrides the behavior.

And, indeed, the help-block class brings the display: block; style (source)…

That’s why your help text is always displayed, even if your usage of Angular 2 validation is perfect.

OK, cool! So now what? You can either get rid of the help-block class (but you’ll lose the style), or you can rewrite your template to not use hidden attribute anymore. And that’s when the ngIf directive comes to play:

<span class="help-block"
      *ngIf="password.dirty
             && password.hasError('required')">
  Password is required
</span>

Et voilà ! Of course, we needed to negate the initial condition of [hidden]="..." (but that’s Boole Algebra 101), and we replaced the pristine test by a dirty test, which is the exact opposite.

Update on 2016-05-12: new alternative solution.

Thomas Queste suggested in the comments an other solution seen on StackOverflow: simply wrapping the error message in its own span inside the span.help-block.

Thanks for the time you spent listening to me. I feel better now. You may get back to work, or get back to read our Angular 2 ebook.


Cyril Lacôte


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


This tip is not specifically about Angular 2, but rather about TypeScript. But since Angular 2, like many of you probably, is what lead us to using TypeScript, we’ll explain this tip in an Angular 2 context, and compare it with JavaScript code used in an AngularJS context.

A typical AngularJS service returning data from the backend

A typical AngularJS service returning data from the backend using $http and promises looks like this:

myModule.service('raceService', function($http) {
    this.getRaceById = function(id) {
        return $http.get('/api/races/' + id)
                    .then(function(response) {
            return response.data;
        });
    };
});

This is quite simple, and using it in your controller is straightforward… as long as you know what the JSON payload looks like. What is a race? What fields does it have? This is easy enough to remember in a small application, when you just developed the backend service. But in a large, complex application, returning more obscure business objects, it’s not easy to know what the payload is, and reading the JS code doesn’t help much.

The same service in Angular 2 and TypeScript

In Angular 2, with TypeScript, the same service would look like (minus imports):

@Injectable()
export class RaceService {
    constructor(private _http:Http) {
    }

    getRaceById(id): Observable<any> {
        return this._http.get(`/api/races/${id}`)
                         .map(response => response.json());
    }
}

Do we have something better, compared to the AngularJS version?

Except for the syntactic sugar (class, arrow function, string interpolation), not much. We know that the service returns an Observable, but we still don’t know what a race looks like.

TypeScript to the rescue

The object returned by response.json() is not an instance of any class you might have defined. It’s just a basic JavaScript object full of properties.

To developers more used to strongly typed languages like Java, there’s not much you can do: if the object doesn’t have any specific type, then you can’t pretend it has one.

But TypeScript, despite having similar concepts, is very different from Java. TypeScript allows defining interfaces which, unlike in Java, can define instance fields. For example:

export interface Race {
    id: number,
    name: string,
    ponies: Array<Pony>,
    startInstant: string,
    status: RaceStatus
}

TypeScript interfaces, a bit like Java generic types, are a purely compile-time construct. The interface doesn’t exist at runtime. But for the TypeScript compiler, it defines the shape of an object. And you can thus define your service as

@Injectable()
export class RaceService {
    constructor(private _http:Http) {
    }

    getRaceById(id): Observable<Race> {
        return this._http.get(`/api/races/${id}`)
                         .map(response => response.json());
    }
}

The difference is subtle, but important: instead of returning an Observable<any> the service now returns an Observable<Race>.

What if

OK, but what if the actual JSON doesn’t have any startInstant field, and has a startTime instead?

TypeScript can’t catch such a problem. At runtime, startInstant will be undefined. But at least, once you’ve found the bug, you can use your favorite IDE to refactor startInstant to startTime, and have all your TypeScript code fixed.

More importantly, when you (or a colleague) have to modify a component using a race, you can just look at the Race interface definition to instantly know what a race object looks like. And you can rely on your IDE to provide reliable auto-completion.

So here’s my ninja tip: define interfaces for the objects returned from the backend. Bonus point: document the fields!


JB Nizet


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


Ce tip concerne plutôt TypeScript qu’Angular 2. Mais comme c’est Angular 2 qui, comme beaucoup d’entre vous sans doute, nous a amené à utiliser TypeScript, on va l’expliquer avec un exemple basé sur Angular 2, et le comparer avec du code JavaScript d’un exemple similaire avec AngularJS.

Un service type ramenant des données du backend

Un service AngularJS typique qui retourne des données en provenance du backend, en utilisant le service $http et les promesses ressemble à ça :

myModule.service('raceService', function($http) {
    this.getRaceById = function(id) {
        return $http.get('/api/races/' + id)
                    .then(function(response) {
            return response.data;
        });
    };
});

C’est assez simple, et l’utiliser dans un controller ne pose pas de problème… à condition de savoir à quoi le message JSON ressemble.

Qu’est-ce qu’une race? Quels champs contient-elle? C’est facile de se le rappeler dans une petite application, alors qu’on vient d’écrire le service côté serveur. Mais dans une grosse application bien complexe, manipulant des objets métiers plus obscurs qu’une course de poneys, ce n’est pas toujours évident de savoir ce que le message contient. Et la lecture du code JavaScript n’est pas d’un grand secours.

Le même service avec Angular 2 et TypeScript

En Angular 2, avec TypeScript, le même service ressemblerait à ça (on vous passe les imports) :

@Injectable()
export class RaceService {
    constructor(private _http:Http) {
    }

    getRaceById(id): Observable<any> {
        return this._http.get(`/api/races/${id}`)
                         .map(response => response.json());
    }
}

Est-ce franchement mieux que la version AngularJS ?

A part le sucre syntaxique (classe, arrow function, interpolation de chaîne de caractères), pas vraiment. On sait que le service retourne un Observable, mais on ne sait toujours pas à quoi une course ressemble.

TypeScript à la rescousse

L’objet retourné par response.json() n’est pas une instance d’une quelconque classe que vous auriez pu définir. C’est juste un objet JavaScript basique, avec quelques propriétés.

Pour les développeur plus habitués aux langages fortement typés comme Java, un objet qui n’a pas de type… n’a pas de type. Et on ne peut pas faire comme s’il en avait un.

Mais TypeScript, bien qu’ayant des concepts similaires à ceux de Java, est très différent de Java. TypeScript permet entre autres de définir des interfaces qui, au contraire des interfaces Java, peuvent contenir des attributs. Par exemple :

export interface Race {
    id: number,
    name: string,
    ponies: Array<Pony>,
    startInstant: string,
    status: RaceStatus
}

Les interfaces, un peu comme les types génériques de Java, sont un concept qui n’existe que pour le compilateur. L’interface n’existe plus à l’exécution. Mais pour le compilateur TypeScript, elle permet de définir la forme d’un objet. Et on peut donc définir son service comme ceci :

@Injectable()
export class RaceService {
    constructor(private _http:Http) {
    }

    getRaceById(id): Observable<Race> {
        return this._http.get(`/api/races/${id}`)
                         .map(response => response.json());
    }
}

La différence est subtile, mais importante. Au lieu de retourner un Observable<any>, le service retourne à présent un Observable<Race>.

Et si…

OK, mais que se passe-t-il si le JSON renvoyé par le serveur n’a pas d’attribut startInstant mais a en réalité un attribut startTime ?

TypeScript ne peut pas détecter ce problème. A l’exécution, startInstant sera undefined.

Mais au moins, une fois que cette erreur aura été détectée, tu pourras utiliser ton IDE préféré pour refactoriser startInstant en startTime, et corriger d’un seul coup tout le code TypeScript utilisant l’attribut incorrect.

Plus important encore, quand tu devras (toi ou un collègue) modifier un composant de l’application qui manipule une course, tu n’auras qu’à examiner l’interface Race pour savoir immédiatement à quoi ressemble un objet de ce type. Et tu pourras compter sur ton IDE pour te fournir de l’auto-complétion.

Voici donc mon ninja tip : definis des interfaces représentant les objets retournés par le backend. Bonus : documente leurs attributs !


JB Nizet


Ninja Squad books


Become a ninja with Angular 2
Cover of ebook Become a ninja with Angular 2

Pay what you want and support charity!


Devenez un Ninja avec AngularJS
Couverture du livre Devenez un Ninja avec AngularJS

Passez de débutant à ninja en AngularJS 1.4 avec un ebook à prix libre et pour une bonne cause !


Ninja Squad books



Formations

Angular 2

19-21 sept. à Paris
26-28 sept. à Lyon
05-07 déc. à Paris
12-14 déc. à Lyon


Suivez-nous


Posts plus anciens