s.dedieu@criteo.com
Senior software development engineer –
#ui-foundation 🛸
s.dedieu@criteo.com
s.dedieu@criteo.com
alexandre.demeure@univ-grenoble-alpes.fr
Enseignant Chercheur #IIHM #UGA
1
2
3
4
Pré-requis
Présentation
Démarrage
Projet
1
2
3
4
Pré-requis
Présentation
Démarrage
Projet
export JAVA_HOME=/chemin/vers/java
export PATH=$JAVA_HOME/bin:$PATHyour/current/path % java -version
java version "11.x.x.x" YYYY-MM-DD LTS
Java(TM) SE Runtime Environment (build 11.x.x.x+x-LTS-x)
Java HotSpot(TM) 64-Bit Server VM (build 11.x.x.x+x-LTS-x, mixed mode, sharing)Téléchargez Android Studio et installez-le.
export ANDROID_SDK_ROOT=/chemin/vers/Android/Sdk/
export PATH=${PATH}:${ANDROID_SDK_ROOT}/tools
export PATH=${PATH}:${ANDROID_SDK_ROOT}/platform-toolsPour les possesseurs de Mac, installez XCode depuis l'App Store.
Installez Git si vous ne l'avez pas déjà.
your/current/path % git --version
git version x.xx.x (Apple Git-136)Installez Node.js si vous ne l'avez pas déjà (préférez la version LTS).
export PATH=/chemin/vers/node/bin:$PATHyour/current/path % node --version
v22.xx.x
your/current/path % npm --version
10.xx.xSurtout ne pas faire du sudo sur Linux
npm install -g @ionic/cliyour/current/path % ionic --version
7.x.xSurtout ne pas faire du sudo sur Linux
npm install -g @angular/cliyour/current/path % ng version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI : 21.0.3
Node.js : 22.13.0
Package Manager : npm 10.9.2
Operating System : darwin arm641
2
3
4
Pré-requis
Présentation
Démarrage
Projet
Ensemble de fonctions pouvant être appelées à l’intérieur de votre code.
Libraries
Votre code est lu, transformé par le framework.
Framework
Ensemble d’outils et librairies facilitant la création et la construction d’applications.
SDK
Qu'est-ce que c'est ?
Un Framework de développement d’applications mobiles.
A quoi ça sert ?
A construire des IPA, APK et PWA publiables sur les stores Android, IOS ou sur un serveur WEB.En fournissant un ensemble d’outils permettant de travailler vite et bien.
SDK
Plateformes
Package manager
Langages Natifs
Components ready to use
Frameworks de développements
1
2
3
4
Pré-requis
Présentation
Démarrage
Projet
ionic start <nom_de_son_application> blank --type=angular{
"name": "kahoot",
"version": "0.0.1",
"author": "Ionic Framework",
...
"private": true,
"dependencies": {
"@angular/animations": "^20.0.0",
"@angular/common": "^20.0.0",
"@angular/compiler": "^20.0.0",
"@angular/core": "^20.0.0",
"@angular/forms": "^20.0.0",
"@angular/platform-browser": "^20.0.0",
"@angular/platform-browser-dynamic": "^20.0.0",
"@angular/router": "^20.0.0",
...
},
"devDependencies": {
"@angular-eslint/builder": "^20.0.0",
"@angular-eslint/eslint-plugin": "^20.0.0",
"@angular-eslint/eslint-plugin-template": "^20.0.0",
"@angular-eslint/schematics": "^20.0.0",
"@angular-eslint/template-parser": "^20.0.0",
"@angular/build": "^20.0.0",
"@angular/cli": "^20.0.0",
"@angular/compiler-cli": "^20.0.0",
"@angular/language-service": "^20.0.0",
...
"typescript": "~5.9.0"
},
"description": "An Ionic project"
}{
"name": "kahoot",
"version": "0.0.1",
"author": "Ionic Framework",
...
"private": true,
"dependencies": {
"@angular/animations": "^21.0.6",
"@angular/common": "^21.0.6",
"@angular/compiler": "^21.0.6",
"@angular/core": "^21.0.6",
"@angular/forms": "^21.0.6",
"@angular/platform-browser": "^21.0.6",
"@angular/platform-browser-dynamic": "^21.0.6",
"@angular/router": "^21.0.6",
...
},
"devDependencies": {
"@angular-eslint/builder": "^21.0.6",
"@angular-eslint/eslint-plugin": "^21.0.6",
"@angular-eslint/eslint-plugin-template": "^21.0.6",
"@angular-eslint/schematics": "^21.0.6",
"@angular-eslint/template-parser": "^21.0.6",
"@angular/build": "^21.0.6",
"@angular/cli": "^21.0.6",
"@angular/compiler-cli": "^21.0.6",
"@angular/language-service": "^21.0.6",
...
"typescript": "~5.9.0"
},
"description": "An Ionic project"
}ng update @angular/cli @angular/corePoints d'entrées de l'application Web
Fichier de configuration de l'application Mobile
ionic serveionic build
npm install @capacitor/android
npx cap add androidnpx cap open android
npm install @capacitor/ios
npx cap add iosnpx cap open ios
1
2
3
4
Pré-requis
Présentation
Démarrage
Projet
Projet Ionic blank
Départ
Une application de Quiz qui permet de :
Arrivée
Définition des interfaces
id
title
description
questions
Quiz
id
text
choices
correctChoiceId
Question
ionic g interface models/<nom_de_mon_interface>
// eg: ionic g interface models/quizid
text
Choice
Définition du service
Créez un service de gestion des Quiz, de leurs Questions et Choix.
Astuce: utiliser la méthode generate de la CLI pour aller plus vite
Le service possède une variable privée qui correspond à un tableau (array) de toutes les Questions existantes.
Le service possède les méthodes:
ionic g service services/<nom_de_mon_service>
// eg: ionic g service services/quizgetAll(): Promise<Quiz[]>;
get(quizId: string): Promise<Quiz>;
addQuiz(quiz: Quiz): Promise<Quiz>;
deleteQuiz(quizId: string): Promise<void>;
updateQuiz(updatedQuiz: Quiz): Promise<Quiz>;Réalisation de la HomePage
Réalisation de la Modale de création d'un Topic
La modale d’ajout de Quiz doit contenir un formulaire permettant de saisir les différents champs de l’objet Quiz.
Documentation utile:
https://ionicframework.com/docs/api/modal (utiliser ModalController)
https://angular.dev/essentials/signal-forms
Lors de la soumission du formulaire, un nouvel objet Quiz doit être créé et renvoyé via la méthode onWillDismiss à la HomePage. Laquelle appellera le QuizService pour ajouter le nouveau Quiz à la liste existante.
Réalisation de la page de détail d'un Quiz
Un clic sur un objet Quiz de la HomePage permet d'accéder à la page de détails de cet objet Quiz.
La page doit afficher toutes les Questions sous forme d’ion-item.
Documentation utile: https://ionicframework.com/docs/api/list https://ionicframework.com/docs/api/item
Elle possède aussi un bouton d'édition qui provoque l’ouverture de modale, qui contient un formulaire pour modifier le Quiz existant.
npm install --save-dev cypress @testing-library/cypress
npx cypress open{
"extends": "../tsconfig.json",
"include": [
"../node_modules/cypress",
"**/*.cy.ts"
],
"compilerOptions": {
"noEmit": false,
"sourceMap": false,
"types": [
"cypress",
"@testing-library/cypress"
]
}
}import { defineConfig } from "cypress";
export default defineConfig({
viewportHeight: 760,
viewportWidth: 360,
e2e: {
baseUrl: 'http://localhost:8100'
},
});import '@testing-library/cypress/add-commands'HomePage
Le quizService doit retourner uniquement des Observables
Les méthodes de:
doivent à présent retourner des Observables.
getAll(): Observable<Quiz[]>;
get(quizId: string): Observable<Quiz>;Pour cela, changez la variable topics en BehaviorSubject et utilisez les méthodes asObservable() (pour la récupération) et next() (pour la modification).
Affichage des données crées dans l'application
npm i @angular/fire --legacy-peer-depsAffichage des données crées dans l'application
export const environment = {
production: false,
firebaseConfig: {
apiKey: "<API_KEY>",
authDomain: "<AUTH_DOMAIN>",
projectId: "<PROJECT_ID>",
storageBucket: "<STORAGE_BUCKET>",
messagingSenderId: "<MESSAGING_SENDER_ID>",
appId: "<APP_ID>",
measurementId: "<MEASUREMENT_ID>"
}
};Ne pas commiter d'informations sensibles
git rm --cached src/environments/environment.ts
// do the same for production if neededProvide Firestore
bootstrapApplication(AppComponent, {
providers: [
...
provideFirebaseApp(() => initializeApp(environment.firebaseConfig)),
provideFirestore(() => getFirestore()),
],
});Affichage des données crées dans l'application
Continuer en utilisant la documentation de l'API
import { Firestore, collection, collectionData, doc, docData } from '@angular/fire/firestore';
export class UserProfileService {
private firestore: Firestore = inject(Firestore); // inject Cloud Firestore
getAll() {
// get a reference to the user-profile collection
const userProfileCollection = collection(this.firestore, 'users');
// get documents (data) from the collection using collectionData
return collectionData(userProfileCollection, {idField: 'id'}) as Observable<UserProfile[]>;
}
getById(id: string) {
// get a reference to the user-profile doc
const userProfileDoc = doc(this.firestore, `users/${id}`);
// get document (data) from the doc using docData
return docData(userProfileDoc, {idField: 'id'}) as Observable<UserProfile>;
}
}import { Firestore, addDoc, setDoc, deleteDoc } from '@angular/fire/firestore';
export class UserProfileService {
private firestore: Firestore = inject(Firestore); // inject Cloud Firestore
add(user: User) {
// get a reference to the user-profile collection
const userProfileCollection = collection(this.firestore, 'users');
// add document from the collection using addDoc
return addDoc(userProfileCollection, user);
}
edit(user: User) {
// get a reference to the user-profile doc
const userProfileDoc = doc(this.firestore, `users/${id}`);
// add document from the collection using addDoc
return setDoc(userProfileCollection, user);
}
delete(user: User) {
// get a reference to the user-profile doc
const userProfileDoc = doc(this.firestore, `users/${id}`);
// delete document from the doc using deleteDoc
return deleteDoc(userProfileDoc);
}
}Installation de firebase emulator
# install firebase CLI
npm i -g firebase-tools
# login to firebase account
firebase login
# init frebase conf / link to existing project
firebase init
◉ Firestore: Configure security rules and indexes files for Firestore
◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
◉ Emulators: Set up local emulators for Firebase products
? Please select an option: Use an existing project
? Select a default Firebase project for this directory: (Use arrow keys)
❯ m2pgi-topic-manager (m2pgi-topic-manager)
# validate all unitl
? What do you want to use as your public directory? www
? Configure as a single-page app (rewrite all urls to /index.html)? No
? Set up automatic builds and deploys with GitHub? No
✔ Wrote www/404.html
? File www/index.html already exists. Overwrite? No
=== Emulators Setup
? Which Firebase emulators do you want to set up? Press Space to select emulators, then Enter to confirm
your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to
proceed)
◉ Authentication Emulator
◉ Firestore Emulator
◉ Hosting Emulator
Le service possède des méthodes pour:
ionic g service services/<nom_de_mon_service>
// eg: ionic g service services/authcreateUser(
email: string,
password: string
): Promise<UserCredential>;
signIn(
email: string,
password: string
): Promise<UserCredential>;
signOut(): Promise<void>;
isConnected(): User;
ionic g page pages/<nom_de_ma_page>
// eg: ionic g page services/loginRéalisation des pages formulaires register & login
Ajouter un Guard pour éviter qu'un utilisateur non-connecté n'accède aux pages home et quiz-details
Ajout d'un Router Guard
Ajout de la confirmation de l'email et la récupération d'un mot de passe oublié
Ajout de la fonctionnalité de propriété et partage d'un Topic
Ecrire ses Security Rules Firebase