Récents articles

Cours logiciel - Electron

Chap 6 : Build, package et distribution (installateur) de…

Nous avons vu au chapitre précédent comment améliorer l’UI de notre application avec un système permettant à l’utilisateur de choisir son thème. Cela se fait beaucoup actuellement sur les applications pour reposer notamment les yeux lors d’une utilisation nocturne. Nous avons aussi vu comment sérialiser simplement et rapidement des données utilisateurs concernant les préférences et paramètres de l’application via de simples fichiers JSON.

Le code source concernant ce chapitre est disponible sur mon Github.

 

Principe global

Dans ce sixième et dernier chapitre de cette série consacré à l’utilisation de Electron, nous allons voir comment packager notre application afin de la distribuer. Pour cela nous allons utiliser le très bon module Electron-builder pour créer nos installateurs. On va installer ce module en tant que dépendances de dév :

  • npm i electron-builder -g

 

Nous allons devoir réaliser deux principales étapes afin de créer notre installateur :

  1. Builder notre application Angular en mode production,
  2. Packager le précédent build via Electron-builder.

 

Génération du build Angular en mode prod

Cette première étape va consister à créer un bundle de notre application. On va demander à Angular de builder notre application en mode production afin de compiler l’ensemble de nos composants, contrôleurs et pages web avec nos modules NPM, afin de passer d’un dossier de quelques centaines de Mo à un build ne pesant que quelques Mo.

Nous allons devoir effectuer quelques modifications de code, car actuellement on ne fait que build notre application dans un environnement de développement via notre serveur local.

 

Chargement de la page d’accueil

Pour le moment on demandait à Electron de charger à l’initialisation de la fenêtre, le rendu du serveur local de Angular via :

win.loadURL('https://localhost:4200/')

On va ajouter du code permettant de demander le chargement de index.html de notre build dorénavant :

On va demander de charger un fichier et non plus une URL, en indiquant via le paramètre protocol. Le chemin correspond au fichier index.html dispo dans notre build, situé dans le dossier ‘dist’ de Angular. Le paramètre slashes est extrêmement important pour Angular, afin de permettre le routage des diverses pages au sein de notre application.

 

Activer le Hash (#)

Etant donnée que l’on crée une SPA ( Single Page Application ), on peut observer des # dans notre URL, mais pas pour tout le monde, puisque Angular le cache dans les dernière version, et cela pose problème.

En effet avec le serveur de dév, tout fonctionne bien. Mais une fois passé en mode production, on arrive plus à afficher nos pages web correctement, car l’URL est faussé sans notre #. Pour cela, on va devoir le spécifier dans notre module principal de routing, d’utiliser le hash :

 

Base des liens

On va aller modifier la base de l’ensemble des liens de notre application, disponible dans notre index.html afin qu’il corresponde avec Electron :

<base href="./">

 

Cible de build

Dans le fichier de configuration de build de Angular, tsconfig.json, on va modifier la ligne suivante :

  • « target »: « es2015 »

par :

  • « target »: « es5 »

 

Génération du build

Dernière étape, on va générer le build Angular via :

  • ng build –prod

Le build est dispo sous /dist.

 

Pensez à tester ce build de production directement avec Electron avant de passer à l’étape suivante, via la commande :

  • electron .

Sans utiliser notre arguments –devTools, on demande à electron de tester notre build précédemment crée et non le serveur de développement de Angular.

 

Tout fonctionne pour moi, on peut passer à l’étape finale 😎

 

/!\ Attention à bien vérifier les liens vers vos assets, qu’ils soient bien relatif et non absolue, sinon vous risquez d’avoir des soucis et ne seront pas trouvé dans votre app Electron !

 

Package du build via Electron-builder

Vous avez de disponible quelques modules pour vous permettre de vous faciliter la vie pour créer votre installateur. En voici les principaux :

Comparatif des modules de build/package les plus populaires

Je vous propose de partir sur le plus populaire du moment de Github, à savoir Electron-builder. Mais vous pouvez partir sur celui qui vous fait plaisir, je n’ai pas essayé les autres mais je présume qu’ils doivent chacun faire le boulot !

 

Du coup avec le notre de module, c’est plutôt simple. On a juste à définir de nouveaux comportements dans notre fichier main.js. Je vous montre la spécification minimal, la plus simple pour générer un installateur. De nombreuses autres options sont disponible sur le site de Electron-builder, que cela soit pour faire un build Window, Linux ou macOS.

appId : nom de l’application

compression : définit le niveau de compression des données de notre application dans l’installateur

win : on définit ici les options pour un build pour window, à savoir la cible ainsi que le fichier d’icone pour notre application

electronDowload : permet de mettre en cache les utils et dépendances nécessaire à Electron builder afin de compiler notre installateur

directories : on définit le dossier d’output pour notre installateur

nsis : c’est la cible concernant un build pour window, on définit les options ici de l’installateur. On lui spécifie que on veut laisser le choix à l’utilisateur pour installer sur une session ou en global, la possibilité de choisir son dossier d’installation ainsi que de supprimer ou non les données de l’application en cache une fois celle-ci de supprimé

files : c’est ici que l’on spécifie à Electron builder les fichiers nécessaires au bon fonctionnement de notre application. On lui donne notre point d’entrée de notre app qui est main.js, ainsi que notre package.json ou l’ensemble du fonctionnement y est spécifié, et enfin le build de production généré par Angular précédemment

 

Pour générer l’installateur, ouvrez votre console dans le dossier du projet et tapez :

  • electron-builder

Il va télécharger les dépendances et utilitaires nécessaire pour créer l’installateur. Vous pouvez lui spécifier des arguments pour définir quelle plateforme et quelle architecture cible vous souhaitez pour votre/vos installateurs.

Dans votre dossier de sortie de Electron builder, sous /distElectron, vous aurez à la fois un dossier avec l’ensemble de votre application buildé et packagé prêt à fonctionner ( on peut appeler ça une installation dite portable, d’un simple copié/collé vous partagez votre app) ainsi que d’un installateur au format .exe traditionnel.

 

Astuce : builder en mode offline

Electron-builder va descendre certaines extension pour réaliser le build. Si vous souhaitez réaliser des builds en mode offline, sur un pc n’étant pas connecté à internet, vous pouvez mettre une variable d’environnement pour forcer le cache de electron builder dans le dossier spécifique de votre choix :

  • set ELECTRON_BUILDER_CACHE= »votre_dossier »

 

Vous aurez ainsi dans ce dossier les éléments suivants :

ELECTRON_BUILDER_CACHE :

  • votre_dossier
    • nsis
      • nsis-x.x.x.x
      • nsis-ressources-x.x.x
    • winCodeSign
      • winCodeSign-x.x.x

 

Vous aurez plus qu’a récupérer ce dossier, et de les déposer via usb sur votre nouvel ordinateur qui ne dispose pas d’un accès internet. N’oubliez pas de re-set la variable d’environnement sur ce dernier pc pour lui indiquer le bon chemin pour accéder à ce même dossier.

 

Conclusion

On arrive avec de sixième chapitre à la fin de la série consacré à comment débuter sur Electron. Vous êtes désormais capable de :

  • Initialiser un nouveau projet, développer avec un serveur de dév en local avec hot reload du frontend & backend,
  • Créer votre première fenêtre avec persistance des données utilisateurs,
  • Gérer la communication entre render & main process, gérer la communication entre composant de Angular,
  • Builder un projet Angular, packager votre application Electron.

 

Cours logiciel - Electron

Chap 5 : Customisation de l’UI (light & dark…

Nous avons vu au chapitre précédent comment créer notre éditeur de texte, comment communiquer du render au main process via le module IPC afin d’interagir avec les fichiers disques via les API de NodeJS.

Pour ce cours-ci nous allons nous consacrer sur une fonctionnalité apprécié en ce moment, à savoir comment avoir un thème sombre et clair, et comment enregistrer ces données-ci afin de les récupérer à chaque ouverture du logiciel. Une rapide ouverture à la programmation réactive Observer/Observable via la librairie RxJS afin d’implémenter une fonctionnalité pour améliorer l’UX de notre logiciel, afin de renseigner le nom du fichier texte actuellement ouvert par l’utilisateur.

Ce cours sera donc principalement consacré à l’amélioration de l’UI pour l’utilisateur.

Le code source concernant ce chapitre est disponible sur mon Github.

Résultat du cours

 

Mise en place du système de persistance

Je vous propose d’ajouter une fonctionnalité, permettant de sauvegarder l’état du thème choisit, pour qu’il puisse être à jour à chaque lancement de l’application et que l’on ne soit pas obligé de le re-sélectionner. D’une manière général, je vous propose un moyen simple afin de sauvegarder et charger des paramètres utilisateurs en cache.

Pour sauvegarder des données, vous pouvez très bien créer une base de données plutôt traditionnel afin de stocker vos informations nécessaire au fonctionnement de l’application. Mais pour notre application qui reste extrêmement minimaliste, je vous propose la sérialisation des data dans un simple fichier JSON. Si vous souhaitez néanmoins rester sur une BD traditionnel, vous devriez regarder vers SQLite database, ou encore IndexedDB sur NPM.

 

Première chose, on va installer un simple module nous permettant de gagner du temps quand à la persistance de fichier JSON.

  • npm install electron-store –save

Souvenez vous que nos fichiers seront disponible dans le dossier %Appdata% de votre ordinateur, dans le dossier du nom de votre application.

On commence par vérifier si notre fichier JSON de sauvegarde existe au préalable sur l’ordinateur. Si celui-ci existe on ne fait rien en particulier. Dans le cas contraire, on va initialiser les valeurs des nos couples Clés/Valeurs. On souhaite avoir comme paramètre sauvegardé, le type de thème sélectionné ( Light, Dark ou Custom ) mais aussi les codes couleurs hexadécimal de nos différentes parties de notre application customizable, via le thème ‘Custom’. En effet, autant les thèmes Light et Dark sont pré-défini au sein de l’application et non modifiable, autant le thème Custom est modifiable lui.

On ajoute dans notre main process de Electron les bons imports qui vont bien :

L’argument ‘name‘ représente le nom du fichier JSON de sauvegarde, lors de la création de notre objet ‘storage‘.

 

On définit ensuite une fonction qui sera appelé dans notre fonction ‘createWindow‘ :

Comme je vous ai dit plus haut, si le fichier ‘settings.json‘ existe déjà, on ne fait rien. Dans le cas inverse, on va le créer et initialiser :

  • SETTINGS : clé
    • THEME_TYPE : clé, contient le type de thème à appliquer au lancement de notre app
    • CUSTO_PALETTE : clé, contient d’autres clés qui sont nos variables CSS avec leur code couleur hexadécimal qui leur sont associé

 

Thème clair & sombre

Il existe plusieurs façon de créer son propre système de thème pour son application. Nous allons voir une méthode très simple qui utilise les variables CSS. Au lieu d’affecter une couleur en dur à un composant HTML via son fichier CSS ( code en hexadécimal ou RGB ), on va désormais lui affecter une variable. C’est celle si que l’on va aller modifier selon no thème. Cela nous permet ainsi de bind plusieurs couleurs au même composant. Je vous propose de créer un thème clair, foncé, et un custom, auquel on pourra lui affecter au sein même de notre application une couleur modifiable à la volée.

 

Création des différents modèles de thèmes 

Premièrement, on va créer  une énumération définissant nos différents type de thème que l’on peut choisir:

 

Ensuite, nous  allons créer une interface permettant de créer des objets du même type :

 

Dans le même fichier précédent, on va maintenant créer 3 objects correspondant à nos 3 thèmes. Nous allons leur affecter un type ( Light, Dark ou Custom ) et leur définir l’ensembles des propriétés CSS que l’on souhaite modifier. Les propriétés CSS ont été réduite volontairement pour gagner en lisibilité, vous pouvez retrouver l’ensemble des propriétés du projet via son dépôt Github. Si on souhaite modifier par exemple seulement la couleur de fond de notre application :

Le mot clés export nous permet d’y accéder en dehors de ce fichier.

 

Mise en place de l’interface pour la sélection du thème

Pour la vue de notre page de paramètres, faisons quelque chose de simple. On va disposer d’un groupe de bouton radio, permettant une sélection unique du thème. Cela nous rampement de choisir entre Light, Dark et Custom. Les deux premiers thèmes ayant des couleurs définit dans notre application, seul le Custom pourra être modifiable, histoire de laisser un maximum de liberté à l’utilisateur dans le choix de ses couleurs. Pour la vue, rien de bien complexe :

On ajoute juste une condition, dans le cas ou l’utilisateur choisit le thème ‘Custom’, on affiche un sélecteur de couleur pour chaque item modifiable de notre application. Pensez d’ailleurs à installer ce module que j’apprécie fortement, un color picker simple qui permet de choisir une couleur en héxadecimal, en RGB ou via un arc-en-ciel de couleur, et qui propose une multitude de fonctionnalités via son api, installable via :

  • npm install material-community-components –save

Petit aperçu du module :

Plutôt sympa non ?😎

 

Passons maintenant au contrôleur de notre page de paramètres. Nous devons définir des attributs pour lier nos boutons précédemment expliqués :

  • availableTheme : Tableau contenant les thèmes disponible à la séléction, responsable de la création des boutons radio
  • aliasTypeTheme : cet alias est un bind à notre énumération précédente, qui contient les trois type de thèmes. Cela nous permet de pouvoir faire dans la vue notre comparaison, et afficher le color picker si et seulement si l’utilisateur à sélectionné le thème Custom
  • activeTheme : c’est le thème actuellement activé

 

Concernant le constructeur du composant, on va créer une instance de ElectronService, permettant de discuter du render process au main process et vice versa :

On initialise nos thèmes disponible pour créer nos boutons radio.

 

Système pour initialiser un thème au démarrage de l’app via Electron-store

On va déléguer la gestion des préférence utilisateurs à un service, un singleton. Créons le via la CLI de Angular :

  • ng generate service ThemeManager

On va lui définir un attribut correspond au thème actif, et un second correspondant lui aussi au thème actif, mais qui sera un BehaviorSubject ( le but de celui-ci et de mettre à jour le thème actif au lancement de l’application , lorsque celle-ci chargement au démarrage les préférences de l’utilisateur) :

 

Concernant le constructeur du service, on va créer une instance de ElectronService permettant de contacter le main process :

On initialise par des valeurs random nos deux précédents attributs (je vous l’accorde niveau QUALITÉ du code, on a fait mieux hein 😅). et on envoi une notification au main process sur le canal ‘loadUserSettings‘.

 

On va définir dans le main process la méthode permettant de lire dans notre fichier JSON de sauvegarde, les données des préférences (définit par notre clé ‘SETTINGS’, et de l’envoyer au render process via le cannal ‘responseLoadUserSettings‘:

 

On réceptionne dans le thème manager les données d’initialisation envoyé par le main process :

On actualise notre thème actif, la palette de couleurs pour le thème ‘CUSTOM’,  et on met à jour notre BehaviorSubject pour mettre la vue à jour concernant le thème actif, et enfin on appelle une méthode permettant d’appliquer notre thème :

On parcours les variables CSS du thème actuel, et on va les appliquer à notre document. Voilà, notre thème est appliqué au démarrage ! 😄

 

La dernière étape consiste à mettre à jour le modèle de nos boutons radio suite au chargement du thème initial. On ajoute une fonction dans le constructeur du composant de la page paramètres, afin qu’il soit notifié dès que le thème actif de notre service ThemeManager change. Voilà pourquoi je l’ai définit en tant que Observable, pour lui attacher un observateur. On va pouvoir subscribe a ce Subject de la façon suivante :

 

Système pour appliquer le thème courant

Maintenant que au lancement de notre application nos préférences sont lues et appliqués, on souhaite pouvoir changer de thème durant l’utilisation de notre application. On retourne sur le contrôleur de notre page de paramètre, et on ajoute la fonction suivante :

Cela va nous permettre de mettre à jour le thème actif pour nos boutons radio mais aussi de l’appliquer, via le ThemeManager.

 

Système pour sauvegarder le thème courant

Nouvelle fonctionnalités qui peut être cool, c’est de pouvoir enregistrer l’état courant de notre application, concernant le thème actif actuellement. Très simple, on va ajouter une seule ligne à la méthode expliqué juste avant, changeTheme() disponible dans le contrôleur de notre page ‘SETTINGS‘ :

Cela permet à chaque changement de thème, ou de couleur sur le color picker pour le thème CUSTOM ( car cette méthode d’actualisation est aussi appelé lors d’une modification de couleurs ) d’envoyer une notification à notre main process sur le canal ‘saveSettings‘, avec notre thème actuel en data.

Dans le main process, nous ajoutons une méthode permettant de réceptionner le thème actuel :

Et on met à jour notre fichier JSON contenant nos préférences utilisateurs, via Electron-store.

 

 

Indication de la page en cours d’exécution

Vous allez avoir besoin d’un nouveau module, permettant de faire de la programmation réactive :

  • npm install rxjs –save

Histoire d’améliorer l’interface utilisateur, je vous propose d’ajouter au centre de notre footer, une indication pour rappeler à l’utilisateur sur quel page il se situe au sein de notre application. Pour cela, on va définir une énumération contenant l’ensemble des pages de notre application :

 

Ainsi lorsque l’utilisateur va changer de page via les boutons de navigation situé en haut de notre application, on demandera une mise à jour du footer. Et pour cela, on va avoir besoin d’un service. On va créer ce service depuis la CLI de Angular :

  • ng generate service FooterUpdateService

 

Ce service va nous permettre d’échanger des données entre nos différents composants. Il se compose de la façon suivante :

On définit un BehaviorSubject. Ceci est un type de la librairie RxJs, qui propose de réaliser de la programmation réactive. Cela est grosso modo de la programmation qui suit le paradigme Observable et Observer. Ce menuStateSubject est un observable. Le ‘behavior‘ indique que c’est un observable, qui sera initialisé dès sa création avec un état pré-défini. Vous pouvez le voir dans le constructeur du service, on lui définit l’état HOME. Si vous souhaitez de pas lui définir d’état en particulier à sa création, vous pouvez utiliser simplement un Subject à la place du BehaviorSubject.

On a une première méthode, updateMenuStateSubject, permettant de lui envoyer un nouvel état.

La méthode getMenuStateObservable permet de renvoyer notre observable, nous l’utiliserons juste après.

 

Le but de ces observables, et d’y attacher des observateurs, ou juste de pouvoir subscribe au sujet. Cela permet de notifier à chaque changement d’état de notre Observable,  ses observateurs et de pouvoir faire des actions en conséquence.

 

On va ajouter dans le contrôleur de notre Header, une fonction permettant de mettre à jour l’état de notre Observable, définit dans le service précédent :

N’oubliez pas d’ajouter au constructeur de notre contrôleur Header,  l’appel au singleton de notre service via ‘public footerService: FooterServiceUpdate‘. On ajoute un argument à cette fonction, du type de l’énumération précédemment crée, afin de déterminer quelle page on ouvre.

 

On ajout ensuite le bind (click) dans notre vue sur chacun de nos boutons, qui nous permettent de changer de page. Ils permettent dorénavant de mettre à jour notre observable :

 

On ajoute dans la vue du footer une variable permettant d’afficher le contenu d’une variable qui sera définit dans son contrôleur :

 

On va ajouter dans le contrôleur du footer, l’attribut précédemment utilisé pour l’affichage de l’état courant du menu :

 

Et voilà le résultat !

Résultat de l’actualisation du footer

 

 

Conclusion

Nous venons de voir quelques pistes afin d’améliorer l’UI pour notre application, ainsi qu’une piste pour sauvegarder les préférences de l’utilisateur. Nous aurons aussi vu une rapide approche sur la bibliothèque RxJS, permettant de suivre le paradigme Observable/Observer.

 

Le 6 eme et dernier chapitre de cette formation est consacré au build & package de notre application, afin de pouvoir la distribuer comme n’importe quel logiciel.

 

Cours logiciel - Electron

Chap 4 : Affichage pour l’édition, écriture de fichier…

Nous avons vu au chapitre précédent comment réaliser un simple appel à NodeJS via le module de communication IPC, afin d’éffectuer un appel au système de fichiers pour nous remonter des fichiers textes disponible dans un dossier précis.

Nous allons maintenant nous attaquer à une nouvelle fonctionnalité, nous permettant lors qu’un clique sur un fichier affiché dans notre explorateur de fichier, d’afficher son contenu dans un nouvel espace.

Le code source concernant ce chapitre est disponible sur mon Github.

Résultat du chapitre

Affichage d’un fichier

Notifier le main process

On va reset les classes permettant de surligner le fichier sélectionné, sur l’ensemble de nos fichiers listé dans notre explorateur.

On va ensuite activer seulement le surlignage pour le fichier actuellement sélectionné.

On envoi une notification au main process via le module IPC, sur le canal pingDisplayFile, en lui envoyant en donnée le chemin relatif de ce fichier.

 

Réponse du main process

On écoute sur ce même canal avec le module IPC.

On va lire le contenu du fichier, via son path précédemment envoyé, via le module fs de Nodejs.

Je récupère aussi le nombre de lignes que contient le fichier, cela nous permettra d’indiquer les lignes dans notre éditeur de texte.

Je créer un objet qui réunit ces deux résultats, afin de l’envoyer au render process via le canal responseFileContent.

 

Affichage du fichier dans le render process

La première fonction me permet de mettre mon attribut fileContent à jour via le nouveau fichier précédemment envoyé, ainsi que l’attribut lineNumber pour le compteur de nombre de ligne.

La seconde fonction va permettre de sauvegarder notre nouveau contenu affiché, et de l’enregistrer sur notre disque à la place de notre ancien fichier. On envoi une notification via le canal saveFile, en lui donnant en paramètre un object qui contient notre fichier, son contenu ainsi que son chemin d’accès.

 

On va ensuite construire notre page HTML pour affiche d’une part le contenu de notre fichier d’une façon éditable, mais aussi d’avoir à proximité un compteur de ligne pour se référer.

Cette disposition de flexbox me permet d’avoir deux colonne, via fxLayout= »row » :

  • lineCounterDisplay : est la partie pour le compteur de ligne. Le trick est de créer une division par chiffre de ligne via le bind angular *ngFor. Pour cela j’ai créer un tableau qui contient n item qui est le nombre de ligne du fichier, et qui sont incrémenté de 1 entre chaque item. Le contenu est bindé via J’ai réaliser via la fonction suivante :

 

  • textEditorDisplay : est la partie pour l’édition du fichier texte. Rien de bien spécial, c’est juste un textArea, qui permet d’afficher et de taper du texte. On le bind avec [(ngModel)] pour l’associer à l’attribut de notre contrôleur qui contient les données du fichier texte, envoyé auparavant par notre main process. On utilisera un second bind, (input), qui sera affecté à la fonction précédemment présenté. Celle-ci permet de déclencher la fonction à chaque changement fait dans le textArea. Cela permet de recalculer en temps réel le compteur de ligne à afficher.

 

Sauvegarde du fichier sur le disque

On utile le module fs de NodeJS pour sauvegarder notre fichier fraîchement modifié.

 

Conclusion

Vous pouvez rendre plus complexe votre éditeur de fichiers en y ajoutant certaines autres fonctionnalités tel que :

  • Une sauvegarde automatique via un timer, ou même à chaque ajout/suppression du moindre caractère ?
  • Proposer des outils afin de customiser la couleurs, taille, ou type de police ?

 

Direction pour le prochain chapitre qui abordera comment créer des thèmes clair et sombre ( pour reposer les yeux la nuit ), comment gérer le stockage de données utilisateurs, et enfin un rapide tour sur la programmation réactive via le paradigme Observer/Observable via la bibliothèque RxJS !

 

 

Cours logiciel - Electron

Chap 3 : Explorateur de fichier redimensionable, lecture de…

Préface

Nous avons vu au chapitre précédent comment réaliser la barre d’outils principal du logiciel.

Nous allons maintenant rentrer dans le vif du sujet pour la réalisation d’un explorateur de fichier texte basique.

Le code source concernant ce chapitre est disponible sur mon Github.

Résultats du cours

 

Explorateur de fichiers redimensionable

C’est tout bête, mais il va arriver à un moment ou à un autre que l’on tombe sur des noms de fichiers plus ou moins long, donc certains pourrait être tronqué. Autant faire quelque chose de propre, et donner la possibilité à notre explorateur d’être redimensionable par l’utilisateur.

Depuis le dernier chapitre, j’ai légèrement modifié l’architecture du projet afin de le rendre plus maintenable pour la suite des tutoriels. En voici une présentation simplifié :

Diagramme général
  • Module App
    • appComponent.ts
    • appComponent.html
    • appComponent.scss
    • appRouting.ts
    • Module Settings
      • settingsComponent.ts
      • settingsComponent.html
      • settingsComponent.scss
      • settingsRouting.ts
    • Module Home
      • homeComponent.ts
      • homeComponent.html
      • homeComponent.scss
      • homeRouting.ts
    • Module Projects
      • projectsComponent.ts
      • projectsComponent.html
      • projectsComponent.scss
      • projectsRouting.ts
        • File Explorer
          • fileExplorerComponent.ts
          • fileExplorerComponent.html
          • fileExplorerComponent.scss
        • File Editor
          • fileEditorComponent.ts
          • fileEditorComponent.html
          • fileEditorComponent.scss

 

 

Pour la partie graphique de notre file explorer, il va être composé d’une toolbar pour permettre d’ouvrir un dossier, une partie pour afficher nos fichier en colonne, et enfin un grabber nous permettant de modifier la taille de notre fenêtre :

On va utilise une directive de angular pour nous permettre de bind la largeur de notre file explorer [style.width.px]=’divWidth’.

Pour la partie de style, rien de bien sorcier, juste de prévoir de changer le curseur de souris lorsque l’on passera sur le grabber afin de faire remarquer à l’utilisateur que la fenêtre est modifiable :

 

La partie la plus intéressante et ou se passe la magie de notre grabber est dans notre contrôleur. On va définir :

  • un boolean, pour savoir si on a le clique enfoncé ou non,
  • une largeur de fenêtre,
  • une ancienne largeur de fenêtre pour connaître les déplacements.

 

Dernière étape, on va devoir ajouter des listener d’actions :

  • Un pour savoir quand on bouge la souris,
  • un autre pour savoir quand on enfonce le clic,
  • et un dernier pour savoir quand on relâche le clic

Dans l’ordre, cela va nous pouvoir de modifier la taille en temps réel, de savoir quand effectuer cette action, et savoir quand l’arrêter :

 

 

Explorateur basique de fichier texte

On souhaite avoir  un système qui puisse lister l’ensemble des fichiers textes d’un dossier, et nous l’afficher sous une forme de liste au sein de notre logiciel. Cela nous permettra d’un simple clique de pouvoir ouvrir tel ou tel fichier texte à modifier.

 

Demande de fichier depuis le Frontend

On va ajouter un bouton nous permettant à son click, de notifier le backend afin d’ouvrir une fenêtre de dialogue pour sélectionner un dossier, dans lequel on souhaite récupérer l’ensemble des fichiers textes qui y sont situé. Rien de bien complexe pour la partie graphique, juste un bouton contenant une icone, qui à son click sera bindé avec l’appel de ‘openFolderDirectory()’. L’utilisation de la flexbox nous permet de positionner le boutton sur le côté gauche de la div.

 

Dans le contrôleur on va ajouter la fonction précédente. Celle-ci fait appel au module ipcRender, qui permet la communication de message du renderProcess vers le mainProcess. Il permet d’envoyer des messages via la fonction ‘send’, ou d’écouter via ‘on’. Cela fonctionne exactement comme des sockets, si vous en avez déjà utilisé. Dans notre cas on va juste envoyer un message vide, une sorte de ping pour exécuter une fonction.

 

Traitement de la demande par le Backend

On va réceptionner la notification venant du front via le module ipcMain dans notre backend, avec sa méthode ‘on’.  La fonction prend un argument ‘event’, permettant de renvoyer un message, ainsi qu’un second argument ‘message’ contenant des données envoyé. Mais rappelez vous, on a juste ping sans envoyer le donnée, cet argument sera donc vide.

Le module dialog va nous permettre de créer une fenêtre de dialogue, avec en argument notre fenêtre principal, suivit d’un dictionnaire d’options permettant de définir si l’on souhaite ouvrir un dossier, un fichier, de définir un nom de fenêtre en particulier, etc.

Cette fonction nous renvoi une promesse, sur laquelle on va pouvoir lui attache deux bloc :

  • .then() : est appelé si l’ouverture du dialog se passe correctement,
  • .catch() : est appelé si une erreur est lancé lors de son ouverture.

Dans le cas ou on a une erreur, on la remonte simplement dans la console du back.

Dans le cas ou tout se passe bien, on va vérifier que l’utilisateur à bien choisit un dossier et n’a tout simplement pas annulé son action par la fermeture de boite de dialogue.  On va alors appelé le module fs de Node qui permet de réaliser des opérations de lectures et d’écritures sur le disque. On va dans un premier temps récupérer l’ensemble des fichiers contenu dans le dossier renseigné pour l’utiliser, puis lui appliquer un filtre via une regexp, permettant de garder seulement les fichiers dont leurs noms se termine par .txt.

On va utiliser le premier argument pour pouvoir répondre au front, en lui envoyant dans un nouveau canal, un tableau contenant les noms de fichiers textes étant dans son dossier de sélection.

 

Affichage de la réponse dans le Frontend

On va réceptionner la réponse venant du Backend via une fonction écoutant sur le même canal que celui utilisé pour l’émission. On va récuperer le tableau de données, et l’associer à un attribut de composant que l’on aura déclaré au préalable.

 

Maintenant que l’on a nos données, on a plus qu’a les afficher comme une liste dans notre vue. On utilisera une mat list item, et on utilisera le bind *ngFor de Angular pour parcourir l’ensemble des items de notre tableau de données.

 

Un petit plus pour l’ésthetisme

Vous avez vu le binding [ngClass] ? C’est une directive de Angular, permettant de lui associer une classe CSS en plus (highlight, dans mon cas), si la condition file.highlight est respecté, soit si et seulement si le booléan est à true. Lorsque l’utilisateur clique sur un fichier, une fonction sera appelé. Celle-ci mettra à jour le boolean de l’ensemble des fichiers à faux, et mettra à true sur celui qui a été sélectionné.

Si vous regarder le code, concrètement cela permet lors d’une sélection d’un fichier, de lui ajouter une couleur plus clair que les autres, pour renseigner de façon plus jolie à l’utilisateur, sur quel fichier il est. Cela aura d’avantage de sens lors du prochain chapitre vous verrez 😉

 

Conclusion

Vous pouvez rendre plus complexe votre explorateur en y ajoutant certaines fonctionnalités comme :

  • Pouvoir remonter dans le dossier parente : pour cela vous n’avez qu’a juste ajouter un bouton ‘parent’, qui va ré-appeler notre fonction de ping du backend, mais en lui envoyant un chemin avec un niveau plus haut.
  • Possibilité d’ajouter un logo à côté de chaque fichier, en fonction de leur type. Vous aurez juste besoin d’une fonction qui split le nom d’un fichier, et qui compare l’extension, et affiche un type d’icone en fonction de celle-ci. A faire soit directement dans la vue avec un binding *ngSwitch, soit d’ajouter un nouvel attribut dans notre FileType.

 

Le prochain chapitre portera sur l’ouverture d’un fichier texte dans notre éditeur, pour pouvoir le modifier et le sauvegarder sur le disque.
 

 

Cours logiciel - Electron

Chap 0 : Présentation de Electron

Présentation

Electron est un framework permettant de développer des applications bureaux multi plateforme ( Linux, Windows, MacOS ) avec des technologies web ( HTML, CSS et Typescript/Javascript ). Il est open source et permet de réaliser très rapidement des applications. Vous pensez que cela n’est pas possible ? Et pourtant vous en utilisez surement sans même le savoir ; Atom, Visual studio, Slack pour n’en citer que les plus gros.

Vous allez donc développer votre application comme si vous développiez un site web.

 

Composition de Electron

composition electron nodejs chronium

 

Electron embarque plusieurs outils/bibliothèque pour permettre d’avoir les mêmes accès qu’un logiciel développé avec un langage plus adapté et/ou de plus bas niveau :

  • Chronium : c’est le navigateur open source qui sert de base au célèbre Chrome de Google. Il va assurer le rendu visuel de l’application.
  • NodeJS : c’est un environnement d’exécution de code javascript. Il permet l’accès au système de fichier de l’ordinateur, ainsi que le réseau.
  • APIs Natives : permet l’accès aux fonctions natives, propres à chacun des OS.

 

Fonctionnement global

Le développement en est extrêmement simplifié, mais aussi accéléré, car vous aurez accès à plus de 300 000 modules sur NPM. C’est une sorte d’hébergeur de module, qui permet de réaliser certaines tâches. Vous ajoutez donc en quelques secondes de nouvelles fonctionnalité sur votre application.

D’autant plus que vous pouvez ajouter un framework pour le frontend pour structurer votre application : Angular, React, VueJS…

 

Vous allez avoir deux processus différent pour faire fonctionner une application tournant sous Electron :

 

  • Main process

C’est le point d’entrée de votre application. Il va contrôler le cycle de vie de l’application. Vous aurez tout les accès depuis ce processus, via les API native ou de NodeJS. Il peut aussi créer de nouveau processus de rendu, ainsi que de démarrer et de quitter l’application.

Ce processus est unique

 

  • Render process

Il va être responsable de la vue de votre application, par le biais d’affichage de vos pages HTML/CSS. Vous aurez accès au javascript pour gérer les contrôleurs et interactions. Mais attention, pas d’accès direct au système.

Chacun des processus de rendu sont indépendant les uns des autres. Si un crash, il n’affecte pas ses voisins. Il peut être caché, permettant d’exécuter du code en arrière plan.

Ce processus peut être multiple.

 

/!\ L’ensemble des fonctionnalités disponible par l’API de Electron ne sont pas forcement accessible depuis les deux types processus. Certains ne seront garanti que dans un seul des deux type de processus.

 

Communication entre Render et Main process

Electron à mit en place un module, appelé IPC, permettant de réaliser une communication ainsi qu’un échange de données entre main et render process, qui est appelable depuis chacun des processus. Cette communication fonctionne sous forme de canaux, et l’échange est bi-latéral. Celle-ci s’apparente à des sockets.

 

Architecture d’une application Electron

Le schéma suivant montre d’une façon simplifié le fonctionnement de base d’une appli Electron.

Architecture simplifiée
Architecture simplifiée
  1. Le package.json est le point d’entrée de votre application. Il va indiquer à Electron ou est le main process,
  2. Le main.js définit votre processus principal. Il va créer la fenêtre graphique pour y appeler le render process.
  3. Le index.html définit votre vue.
  4. Le module IPC permet l’échange d’informations entre les divers processus.

 

Conclusion

Points positifs

  • Stack web facile à apprendre
  • Dév rapide ( hot reload, console chronium, modules NPM… )
  • Cross-platform

Points négatifs

  • Consommation excessive de RAM
  • Taille du bundle ( ~100Mo pour un simple ‘Hello World !’ )

 

Maintenant que vous voyez le fonctionnement global d’un projet sous Electron, je vous propose d’expérimenter vous même, et de réaliser un traitement de texte basique sur le chapitre suivant.

 

 

Cours logiciel - Electron

Chap 2 : Barre d’outils, appel de l’API de…

Préface

Nous avons vu au chapitre précédent comment créer une frameless window basique.

Nous allons y ajouter quelques fonctionnalités de base que doit avoir un logiciel, via sa barre d’outils.

Le code source concernant ce chapitre est disponible sur mon Github.

Résultats du cours

 

Hot reloading du backend

Autant le hot reload des pages web du front se font automatiquement via le module Webpack contenu dans Angular, autant le backend ne s’effectue pas. Pour cela on va ajouter un module npm dans notre projet :

  • npm install electron-reload

Il va nous permettre de créer un nouveau main process de Electron, en lui donnant simplement en argument le chemin de l’exécutable de electron.

Nous lui ajouterons un argument pour permettre un hard reset du module, ce qui évite d’avoir des processus de Electron fantôme qui peuvent persister.

Et enfin un dernier argument, nous permettant de pouvoir injecter des arguments au lancement de electron, et dans notre cas de garder dans notre environnement de dév, le lancement des dev tools de chronium.

 

Barre d’outils via l’API de Electron

Définition de la vue, via des flexbox 

On va introduire des notions de responsive design qui est propre aux stack du web. Ceci nous permet de rendre adaptable la vue d’une page en fonction de la hauteur et largeur de l’écran de l’utilisateur, et ainsi d’en modifier sa disposition. On parle alors de Flexbox. Celles-ci sont déclaré dans les pages CSS, et permette de définir des règles de disposition entre chaque éléments ( des <div> par exemple ). Cela peut définir des règles pour indiquer comment tel ou tel élément doit grossir, réduire, ou encore se disposer en ligne ou colonne avec ses éléments voisin. Un petit module que j’apprécie et qui est disponible sur NPM, va nous permettre d’induire ces flexbox, directement dans les balises du code HTML de la page :

  • npm install @angular/flex-layout

 

On souhaite avoir une barre d’outils comme ceci :

  • Partie gauche :
    • Une icone du logiciel avec un bouton d’accueil
  • Partie du milieu :
    • Le nom du logiciel
  • Partie droite :
    • Une barre d’outils avec des boutons permettant de réduire, de minimiser/maximiser la fenêtre, ainsi qu’un dernier pour fermer la fenêtre

 

1 – Contener Global

On va commencer par créer un contener global ( notre mat-toolbar ), qui va prendre le maximum d’espace possible de son parent, définit par la directive fxFill :

 

2 – Création des 3 sous conteners (définit précédemment)

On utilise la directive fxLayout=’row’ afin de créer 3 conteners sur la même ligne. Quand a fxLayoutAlign=’space-between’, elle va nous permettre de définir le type d’espacement entre chacun d’eux. Celle-ci nous permet de les espacer au maximum des un aux autres.

 

3- Alignement vertical d’un des trois sous conteners

On souhaite qu’ils soient aligné au milieu ce leur ligne. On va donner l’exemple pour le contener de droite. Pour cela, on va ajouter au contener précédent, la directive fxLayout=’column’ pour pouvoir créer des conteners de façon vertical ( rappeler vous que le row permet d’aligner des conteners de façon horizontal), avec le bon fxLayoutAlign=’center’ qui va bien, pour permettre de les aligner au milieu au seins de celui-ci.

Si on reprend notre cheminement depuis le début, on doit normalement avoir un contener fixé à droite de la barre, et qui sera aligné au milieu concernant son axe vertical. On souhaite maintenant avoir y incorporer 3 bouttons d’actions.

 

4 – Boutons d’actions

On va recréer un contener de type row cette fois-ci, nous permettant de grouper l’ensemble de nos trois boutons de façon horizontal. En effet avec le point précédent, nous étions dans un contener de type column, et donc aligné sur l’axe vertical, chose que l’on ne souhaite pas.

Vous n’avez plus qu’a ajouter vos trois boutons, avec l’appel aux fonctions qui seront déclaré dans le contrôleur, via la directive de angular, (click)=’votre_fonction()’.

 

Pour un peu d’esthétisme, j’ai rajouté une classeclass=button hoverBtnWhite, lié dans le fichier CSS, permettant qu’au passage de la souris, la couleur de l’icone et de son background change.

 

 

Définition du contrôleur, via le service Electron

Maintenant que la partie graphique est mise en place, on va passer au contrôleur, permettant d’ajouter des actions à nos jolis boutons 😉

On va ajouter un nouveau module, nous permettant d’accéder à l’API de Electron directement depuis notre contrôleur.

  • npm install ngx-electron --save

On l’importe dans notre module principal, soit App :

import {NgxElectronModule} from 'ngx-electron';

Et on le déclare dans la partie des imports :

import: [ NgxElectronModule ]

Dans notre composant Header.ts, nous aurons besoin d’importer le module ElectronService. En créer un attribut de classe, l’instancier lors de la construction du composant, et se servir du module REMOTE de l’API de Electron. On va alors pouvoir utiliser via ce module, les utilitaires du process main, depuis le render process. Le code suivant vous montre comment lier nos boutons créer précedemment pour leur affecter respectivement les actions  suivantes :

  • fermer la fenêtre,
  • réduire la fenêtre,
  • maximiser,
  • unmaximiser.

 

Materials icons en offline

Si vous utilisez des icons de la librairie Material, soit celle de base de Angular, vous allez les télécharger à chaque lancement de l’app. Cependant, le jour ou vous voulez déployer votre application hors ligne, plus rien de marche, et les messages d’erreurs ne sont pas tellement explicite, vous êtes obligé d’aller chercher dans les requetes HTTP. Pire si comme moi vous avez du déployer une app offline sur iPad, sans n’avoir de console de développeur de iOS, alors autant prévoir les choses à l’avance. On va utiliser un module disponible sur NPM pour pouvoir toujours les avoir dans notre app :

  • npm install material-design-icons-iconfont --save

Et ajoutez les lignes suivantes dans votre fichier de style globale de votre app, soit style.scss :

 

Conclusion

Nous venons de voir comment appeler l’API de Electron depuis notre front en Angular, pour lui ajouter des fonctionnalités simple d’un logiciel.

Nous verrons au prochain chapitre comment créer un explorateur de fichier simple, pour présenter le module ipc de Electron, permettant de communiquer et d’échanger des données entre main et render process.

 

 

Cours logiciel - Electron

Chap 1 : Fenêtre principale, frameless bar, icon, lancement…

Préface

Je vais vous présenter comme installer votre environnement de développement, et créer votre première fenêtre, avec quelques astuces de dév, vous permettant d’accélérer vos rendus.

Le code source concernant ce chapitre est disponible sur mon Github.

Résultat du cours

 

Installation des pré-requis

Vous devrez avoir NodeJS d’installé. Je vous renvoi sur un précédent article qui vous explique les démarches à suivre.

 

Initialisation d’un nouveau projet

On va initialiser une nouvelle application angular avec tout le squelette de base qui va bien, afin de nous faire gagner du temps :

  • ng new Nom_de_votre_app

note : ng est une commande de la CLI de Angular

Sélectionner Yes pour avoir le routing du module de base,

Sélectionner ensuite votre langage pour les feuilles de style, je prends SCSS pour ma part.

 

On va ajouter Electron à notre projet via :

  • npm install --save-dev electron

 

Création de la fenêtre principale

On va créer un fichier main.js. C’est lui qui va servir de fichier principal pour créer notre fenêtre, avec le code suivant :

On va ensuite mettre à jour notre fichier package.json pour lui indiquer le point principal d’entrée pour Electron an ajoutant la ligne :

"main": "main.js"

 

De retour sur la console, déplacer vous au sein du projet, vous allez pouvoir lancer votre application dans electron via la commande :

  • electron .

 

Tadaaaaaaaaaaaaa. Ça ne casse pas 3 pattes à un canard, mais ça à le mérite d’être du développement plutôt rapide ! 😂

Première fenêtre sous Electron !

 

Liaison du serveur de dév de Angular vers Electron

Nous n’avons fait que lier de façon statique la page index.html. Cependant, pour le bon fonctionnement de Angular, il va nous falloir un serveur HTTP qui gère le typescript. Celui de base de Angular fonctionne très bien.

On va modifier notre fichier main.js pour qu’il prenne non plus un fichier en entrée, mais une URL qui pointe vers notre serveur de développement.

Lancer depuis une console le serveur de développement de Angular :

  • ng serve

 

Lancer ensuite depuis une seconde console electron. Vous avez désormais accès à Angular depuis votre application Electron. Vous pouvez avoir accès au rechargement à chaud ( mise à jour de l’UI en direct dès une modification du code ) directement dans Electron.

Angular tourne dans Electron

 

Lancement parallèle 

Pour éviter d’avoir deux console, on va pouvoir automatiser le lancement de Electron et Angular depuis un script.

Dans le fichier package.json, rajoutez les scripts suivants :

La première permet de lancer electron. La seconde quant à elle permet de lancer le serveur local de développement de Angular et Electron de façon concurrentielle.

 

Customization de la fenêtre

C’est dans l’ère du temps, donnons un peu de style à notre application 😎

On va supprimer la barre d’outils toute moche, et y incorporer une toolbar un poil plus joli, qui nous permettra de déplacer notre app, ainsi que de l’agrandir via une double tap.

Ajoutons la librairie de base pour les material UI :

  • ng add @angular/material

Nous n’avons pas besoin de HammerJS, mais belle et bien cependant des browser animations pour Angular material, qui seront à préciser à la suite de cette commande.

 

On va ajouter notre toolbar à notre fichier HTML du composant App

<mat-toolbar class="menu">My App</mat-toolbar>

 

Ajouter à notre module principal App le bon import pour la librairie Material :

import { MatToolbarModule} from '@angular/material'

 

Et ajouter MatToolbarModule dans la déclaration du Module principal, dans la partie Import

 

 

Lancement instantané de l’app ( white blank screen )

Quand on lance l’application, on a un écran blanc temporaire qui s’affiche. C’est une chose que l’on ne souhaite pas avoir au sein de notre application une fois buildé. C’est pour cela que l’on va modifier notre fichier main.js pour demander à Electron d’afficher notre fenêtre seulement une fois que celle-ci sera entièrement chargé, ce qui nous donnera l’impression d’avoir une ouverture quasi instantané.

Pour cela on va créer notre fenêtre et demander à Electron de la cacher dans un premier temps. Ajoutez la ligne suivante en paramètre de création lors de l’appel de la méthode :

  • show: false

On va ensuite rajouter un event, qui sera appelé une fois que la fenêtre sera prête :

Notre application va désormais se lancer directement.

 

Icone de l’application

Pour changer l’icone de votre application sur le bureau de windows, ajouter l’option lors de la création de la fenêtre avec le lien pointant vers une image placé dans votre dossier d’assets :

  • icon: './src/assets/icon/icon_transparent.png'

 

Conclusion

Nous venons de créer très simplement et rapidement une simple fenêtre, avec un chouette esthétisme.

Le prochain chapitre va permettre d’y ajouter de nouvelles fonctionnalités, concernant la barre d’outils.

 

 

Cours web frontend - Angular 8

Chap 5 : Gestion de la navigation via les…

Nous avons vu au chapitre précédent, l’ajout de deux composants dans notre application web, dont un menu de navigation. On va souhaiter maintenant de pouvoir nous balader à travers notre app pour afficher tel ou tel composant. Le code source du projet est disponible ici sur Github.

 

Routing entre component

On va commencer par créer deux nouveaux composants pour correspondre à nos deux onglets du menu :

  • ng generate component acheter
  • ng generate component vendre

Automatiquement, ces deux composants vont être déclarés dans notre app.module.ts.

 

On va créer deux alias pour deux routes différentes dans notre nav bar qui permettront de rediriger vers un composant :

 

On va aller ajouter cette redirection de route dans notre fichier app-routing.module.ts. On ajoute aussi l’import de nos deux composants. Quand au fichier de routing, celui ci est crée lors de la création du module si vous ajoutez l’attribut --routing.

On va dire de charger tel ou tel composant selon l’alias renvoyé par notre nav bar :

 

Redirection d’une route

Une chose qui peut être intéressant, c’est de pouvoir rediriger une route vers un composant spécifique. Par exemple, au démarrage de l’application, on souhaite charger par défaut un onglet spécifique.  Nous allons ajouter une directive de redirection dans le fichier app-routing.module.ts comme cela :

 

On est alors automatiquement redirigé lorsque l’on ouvre localhost:4200 vers localhost:4200/acheter, avec le composant ‘acheter’ d’ouvert :

 

Routing pour entre module

On va créer un nouveau module pour imager notre navigation entre module :

  • ng generate module login --routing

Ainsi que trois nouveaux composants :

  • ng generate component inscription
  • ng generate component connexion
  • ng generate component login

On va se service de login pour créer une seconde nav bar, nous permettant de naviguer au seins du module Login pour nous permettre de choisir entre la page d’inscription et de connexion.

 

On ajoute le nouvel onglet à notre nav bar principal:

 

On ajoute la nav bar secondaire :

 

N’oubliez pas d’ajouter dans le constructeur de login.component.ts, les items du sous menu :

La balise <router-outlet></router-outlet> va nous permettre d’inclure le code HTML des enfants dynamiquement, soit login/connexion ou login/inscription à tout moment lors de la navigation.

 

Il nous reste plus qu’a ajouter les routes des enfants du module Login dans notre fichier de routing principal qui est dans le module app :

 

Lazy loading, ou chargement à la demande

Au fur et à mesure que vous ajoutez des fonctionnalités à votre application, il se peut que celle-ci prennent de plus en plus de temps à s’ouvrir. En effet, c’est lors du démarrage que l’ensemble des pages sont récupérés, que les objets sont construits, etc. Afin d’alléger cette phase, on peut donner une nouvelle directive à angular, lui demandant de charger les modules à la demande seulement. Ces composants ou modules ne seront donc crée que lorsque l’un de ses composant sera appelé lors de la navigation.

Premièrement on va modifier notre appel à notre module Login  dans le fichier de routing principal de notre application :

 

Ensuite, on a juste à donner les nouvelles routes au sein du module enfant :

 

Pre loading

Nous venons de voir comment charger nos modules séparément et à la demande. On peut encore optimiser ces temps de chargement au démarrage.

En effet, une fois le module principal chargé, on pourrait demander à Angular de pouvoir pré-charger en arrière plan les autres modules de l’application, alors même que l’utilisateur peut dors et déjà interagir avec le module principal de l’application. Cela permettra ainsi d’avoir une navigation quasi instantané des autres modules.

Pour cela, on va modifier la stratégie de pré-chargement dans le fichier de routing principale de l’application :

 

 

Cours web frontend - Angular 8

Chap 4 : Créer votre premier component ( header…

Maintenant que nous en savons un peu plus sur les briques logiciels mit à disposition par Angular vu au chapitre précédent, nous allons pouvoir ajouter notre premier composant. Pour l’exemple, nous réaliserons un header pour la navigation à travers notre application et un footer. Je vous joint le code Github du projet si vous souhaitez vous en inspirer. N’oublier pas quand vous récupérer le projet, d’y faire un npm install au sein du projet afin d’installer les dépendances inscrite dans le package.json.

 

Création des components

On va se déplacer à la racine du projet et créer un nouveau répertoire que l’on va appeler Core :

  • cd src
  • cd app
  • mkdir Core
  • cd Core

On va générer nos deux components avec la Cli :

  • ng generate component header
  • ng generate component footer

 

Customization du Header

On va s’en servir pour créer un menu afin de permettre la navigation dans notre application.

La première étape et d’y ajouter le contenu de la vue du component Header dans la vue du composant principal de notre application, qui est app.component. Pour cela, on va ajouter le sélecteur du component Header et l’insérer dans app.component.html. Vous pouvez modifier le sélecteur de celui-ci dans l’entête du header.component.ts :

Dans cette en tête, vous avez :

  • selector : représente la balise HTML à appeler pour afficher la vue du composant de Header, donc son fichier HTML
  • templateUrl : c’est le fichier .HTML de la vue du composant
  • styleUrls : c’est le fichier de style .CSS correspondant au composant

 

On ajoute donc dans le fichier app.component.html la balise suivante en haut de fichier :

<app-header></app-header>

En lançant notre application nous avons le changement suivant :

Qui permet de nous indiquer que le contenu du header s’affiche correctement.

 

 

Ne pas oublier de déclarer notre nouveau composant dans son module respectif. Cli s’occupe de lui affecter la déclaration, mais c’est bon de savoir ce qu’il se passe quand on appelle la Cli :

Déclaration du nouveau composant Header dans son module parent

 

Ajout du menu de navigation

On va pouvoir ajouter un menu. Pour cela on va utiliser des material component, une librairie de base qui permet l’ajout d’élément graphique :

npm install @angular/material @angular/cdk @angular/animations

Dans app.module.ts, on va ajouter l’import de cette librairie  :

import { MatTabsModule } from '@angular/material/tabs';

Puis dans la partie imports, on ajoute MatTabsModule. Ajouter aussi le BrowserAnimationsModule, disponible depuis :

import {BrowserAnimationsModule} from '@angular/platform-browser/animations';

Dans le fichier header.component.ts, on va y créer un tableau à fournir à notre menu pour qu’il puisse avoir des noms d’onglet :

Puis y ajouter notre composant dans le header.component.html :

 

Pour fonctionner enfin, il faut fournir un thème de base à notre application pour Angular/material. Pour cela, aller ajouter la ligne suivante dans le fichier style.css :

@import "../node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css";

Je vous laisse voir la doc, il existe une multitude de code couleur pré existant. Vous pouvez aussi créer le votre.

 

Customization du Footer

On va réitérer les étapes précédentes, à savoir :

Insertion du sélecteur de Footer dans la vue parente, soit à la fin de app.component.html :

<app-footer></app-footer>

 

Création de la <div> du footer :

 

On lui modifie sa feuille de style pour rester fixé en bas du site :

 

 

Et voila le résultat de l’ajout de notre header et footer sur l’application :

 

Dans le prochain chapitre, on va présenter le système de route permettant de naviguer entre les divers composants et module de l’application.

Cours web frontend - Angular 8

Chap 3 : Structure d’un application Angular

Nous avons vu au chapitre précédent comment générer le squelette de base d’une application sous Angular 8. Nous avons vu une multitude de fichiers crées lors de cette génération effectue par Angular/Cli.

Sont-ils tous réellement utiles ? A quoi correspondent-ils ? Je vais vous en présenter les principaux à connaître.

Il faut savoir que Angular permet de créer une multitude de brique logiciel ( composant, service, classe…  ) que l’on va assembler entre eux de façon organisé et distincte ( module ).

 

Structure globale

/e2e

Ce dossier va permettre de rédiger divers test end to end par le framework Protractor

 

/package.json

C’est un fichier json qui va contenir la description de l’ensemble des modules NPM utilisé pour notre application. Vous aurez le choix d’installer ou d’update certains packet en comparant ce fichier. Utilise aussi pour gérer les dépendances nécessaires entre packet.

 

/angular.json

Fichier de configuration qui contient certains hyper paramètres important, tel que le dossier de sortir pour les builds de production, les dossiers contenant les fichiers de styles ou encore les assets, la page HTML principal à afficher, etc.

 

/src

Ce dossier va contenir l’ensemble de nos fichiers sources de notre application

 

Module et composition

Un module est un conteneur, un building block. Il permet de créer des packages distant d’un point de vue fonctionnalité. Par exemple pour un site web simple comme le bon coin, on peut avoir un module pour la gestion des annonces, et un module pour la gestion de l’authentification des comptes.

Ces modules nous apportent une plus fine granularité au sein d’un projet. Cela permet plus tard, d’améliorer l’extensibilité et la maintenabilité du code pour l’ajout de nouvelles fonctionnalités.

Vous pouvez créer un module via la commande Cli suivante :

  • ng generate module [nom du module] –routing

L’option –routing est optionnel, mais nous facilite la tâche. Nous le verrons juste après.

 

Cette commande va nous créer plusieurs fichier. On imagine que notre module s’appelle APP.

  • app.module.ts : c’est le fichier centrale de notre module. On y définit l’ensemble des imports qui seront utilisé dans notre module (librairies NPM), on y définit l’ensemble des composants qui y seront déclaré, mais aussi des services.  C’est quelque peu comme les fichiers H/HPP en C/C++.
  • app-routing.module.ts : c’est le fichier responsable de la navigation entre composant, et donc entre les vues.

 

Component et composition

Un composant est une entité dans angular. Il prend la forme que vous lui donnez. Cela peut très bien être une page d’accueil en entier, comme une simple barre de navigation servant de menu. C’est à vous de choisir encore une fois la granularité que vous donnez aux objets de votre application.

 

Vous pouvez créer un composant via la commande Cli suivante :

  • ng generate component [nom du composant]

 

Cette commande va nous créer plusieurs fichier. On imagine que notre module s’appelle comp1.

  • comp1.component.css : c’est la feuille de style de notre component
  • comp1.component.html : c’est la feuille qui correspond à la partie graphique, la vue
  • comp1.component.spec.ts : c’est un fichier permettant de réaliser des tests, qui seront automatisé avec Protractor
  • comp1.component.ts : c’est le contrôleur de notre component. Il va nous permettre d’y ajouter des fonctionnalités entre la vue, les boutons, la base de données, etc.