TP3
Consignes
-
Lisez toutes les instructions et la grille de correction avant de commencer
-
Vous DEVEZ faire au moins les migrations et les commits demandés mais vous pouvez en faire plus sans problème, tant que vous les documentez correctement
-
L'utilisation de l'IAG pour créer partiellement ou totalement des éléments du travail entraînera automatiquement un zéro et un plagiat
-
Il faut télécharger ce fichier zip
Surlignage et filtre dans la vue Index de TrainerCertification
1. Surlignage
-
Ajoutez le code JavaScript nécessaire pour surligner les rangées (<tr>) dont le nom du Trainer contient la chaîne de caractères qui est entrée dans la boîte de texte.
- La recherche de texte doit ignorer la casse (minuscule ou majuscule).
- Lorsqu'on ajoute des caractères et qu'on les retire tous, le surlignage doit se retirer de toutes les lignes.
Il y a plusieurs façons possibles de résoudre ce problème, mais c'est une bonne idée d'ajouter un id sur <tbody> ou bien un attribut class sur le <td> ou le <a> qui contient le nom du trainer afin de pouvoir les obtenir dans votre code JavaScript.
Le nom de la fonction à coder se nomme highlightByName(). La balise input contient déjà le code nécessaire pour appeler cette fonction à chaque fois qu'un caractère est ajouté ou retiré dans la boîte de texte. Ce comportement se fait grâce au oninput.
Vous pouvez simplement utiliser la propriété de style backgroundColor pour faire le surlignage
![]() |
|---|
2. Filtrage par date
-
Ajoutez le code javascript nécessaire pour filtrer les données en fonction de la date. Vous ne devez PAS faire de requête au serveur pour obtenir les dates filtrées. Ceci doit être fait uniquement en javascript.
-
Il faut seulement afficher les rangées avec une date égale ou supérieure à la date entrée dans le champ date.
-
Le filtrage s'effectue lorsque l'on clique sur le bouton "Filtrer".
-
Encore une fois, il y a plusieurs façons possibles de résoudre ce problème, mais c'est une bonne idée d'ajouter un id sur <tbody> ou bien un attribut class sur le <td> qui contient la date de la certification pour facilement les obtenir dans votre code JavaScript.
Le nom de la fonction à coder se nomme filterByDate(). La balise input contient déjà le code nécessaire pour appeler cette fonction lorsqu'on clique sur le bouton Filter
Pour vous aider avec la comparaison de dates, il est possible de créer un objet de date à partir d'une date en utilisant new Date(dateString) et un élément de type input possède la propriété valueAsDate
![]() |
|---|
Il est possible de filtrer et de surligner en même temps.
Système de filtrage des Trainers sur la page d'accueil
Mise en contexte
Dans cette section, vous devrez compléter le système de filtrage des Trainers sur la page d'accueil afin de permettre à l'utilisateur d'afficher uniquement les Trainers correspondant aux critères sélectionnés. Pour ce faire, vous devrez compléter l'action Filter de TrainerController et la méthode GetAllAsync de TrainerService. Ici, le filtrage est effectué du côté serveur.
Avant d'obtenir un résultat complet et fonctionnel, il y aura plusieurs étapes à compléter.
-
Modifiez l'action Filter du TrainerController afin quelle retourne la vue Index et les trainers filtrés. L'action Filter reçoit la liste des filtres en paramètre. Utilisez la méthode GetAllAsync avec ces filtres pour obtenir les trainers qui respectent les critères.
-
Modifiez la méthode GetAllAsync du service TrainerService pour prendre en compte les paramètres de pagination de TrainerSearchViewModelFilter. Lisez les commentaires dans le code pour plus de détails.
-
Dans la même méthode, il faut également ajouter des Where pour filtrer selon chacun des critères de recherche de TrainerSearchViewModelFilter (il y a 5 filtres à appliquer)
- Pour le filtre par nom, il faut accepter un résultat si le nom OU le prénom contient la chaîne de caractères entrée dans le filtre
-
Il faut également remplir les SelectList dans la même méthode (GetAllAsync) pour afficher les choix à l'utilisateur.
-
Pour le SelectList de certification centers, il faut obtenir le CertificationCenter (une simple string) de toutes les certifications et enlever les doublons, car il est possible que plusieurs certifications aient le même CertificationCenter.
Cette fois-ci le filtrage est effectué sur le serveur en effectuant une nouvelle requête dans la BD.
Voici comment on peut faire une requête pour une condition optionnelle dans Linq et ne filtrer que lorsque l'on sélectionne une valeur dans le filtre.
.Where(x => filter.SelectedCategoryId == null || x.CategoryId == filter.SelectedCategoryId )
C'est le moment de tester, ajouter des commentaires et faire votre commit et votre push
Affichez le détail d'un Trainer dans la page Trainer/Index
- Écrivez du javascript en utilisant jQuery pour ajouter la classe show à l’élément enfant aside lorsqu'on survole le card d’un entraîneur.
- Écrivez du javascript en utilisant jQuery pour retirer la classe show à l’élément enfant aside lorsqu'on ne survole plus le card.
Comme aside est un enfant de card, si l'utilisateur bouge sa souris à l'extérieur de la photo de l'entraîneur vers le aside, la souris est toujours techniquement au-dessus de card et ça ne cause pas d'événement onmouseout. Ça tombe bien, c'est exactement ce que l'on veut!
![]() |
|---|
C'est le moment de tester, ajouter des commentaires et faire votre commit et votre push
Faire fonctionner la pagination
Pour faire fonctionner la pagination, nous allons utiliser plusieurs propriétés importantes présente dans la propriété Items du ViewModel que reçoit la vue Trainer/Index.
-
La première contient l'index de la page actuellement sélectionnée :
PageIndex. (Notez que cette propriété contient la même valeur queselectedPageIndexqui est affichée dans le formulaire. Vous pouvez donc utiliser une ou l'autre pour gérer la pagination. Nous rendrons toutefois le input selectedPageIndex hidden plus tard, pour le moment il est visible uniquement pour les tests). -
La deuxième contient le nombre de pages au total :
TotalPages -
La troisième contient un booléen qui est à true s'il y a une page précédente :
HasPreviousPage -
La quatrième contient un booléen qui est à true s'il y a une page suivante :
HasNextPage
-
Modifiez le code (complètement en bas de la vue Index) pour que toutes les pages disponibles soient affichées dans la pagination. Assurez-vous que le
lide la page sélectionnée ait la bonne classe. -
Ajoutez la logique pour que Previous et Next s'affichent seulement lorsqu'il le faut.
À chaque fois que nous allons cliquer sur un élément de la liste de pagination:
Il faudra changer la valeur de l'élément <input> correspondant au SelectedPageIndex, puis soumettre de nouveau le formulaire.
-
Ajoutez le JavaScript/Jquery dans la vue. Utilisez les attributs data-page-id qui sont déjà présents sur les éléments de navigation pour savoir quelle page est sélectionnée. Voici quelques indications pour vous aider:
- Exécutez une fonction JS lorsqu'un élément de pagination est cliqué.
- Obtenez la valeur du data-page-id correspondant à l'élément sur lequel l'utilisateur a cliqué.
- Obtenez l'élément qui contient l'information du SelectedPageIndex dans le formulaire (libre à vous d'ajouter une classe pour vous aider à l'obtenir plus facilement).
- Modifiez sa valeur (attention aux cas particuliers Previous et Next).
- Soumettez de nouveau le formulaire (pour cela on peut simplement utiliser la méthode
submit()sur l'élément jQuery correspondant au formulaire).
-
Une fois que votre navigation fonctionne bien, mettez le SelectedPageIndex (l'élément mentionné dans le point précédent) en type="hidden" et supprimez le libellé (label associé).
C'est le moment de tester, ajouter des commentaires et faire votre commit et votre push
Générez les vues et le contrôleur (RecordController) du modèle Record
Au moment de générer le contrôleur, il faut le nommer RecordController et non pas RecordsController (Donc, pas de s!). C'est important car les liens existants et les fichiers de traduction utilisent tous Record et non pas Records!
Si vous avez une erreur, assurez-vous d'utiliser la dernière version de toutes les librairies dans votre projet 8.0.X. Pendant la génération, le système met automatiquement à jour la version de la librairie Microsoft.VisualStudio.Web.CodeGeneration.Design qui utilise une version différente. Au moment d'écrire ces lignes, la version des librairies est maintenant 8.0.28, sauf pour Microsoft.VisualStudio.Web.CodeGeneration.Design qui est à 8.0.23.
La génération de contrôleur utilise parfois des @ dans son code et ça cause des erreurs! Vous pouvez simplement remplacer les @ par un nom de variable différent, comme x.
La génération de contrôleur utilise des [bind] pour les actions post de Create et Edit. À moins que vous soyez déjà familier avec leur utilisation, vous pouvez simplement les retirer.
-
Générez un contrôleur MVC avec ses vues pour le modèle Record. (Un lien vers cette vue existe déjà dans la barre de navigation)
-
Créez un ViewModel (RecordViewModel) qui contiendra un propriété Record ainsi que les SelectList correspondants aux éléments
<select>des formulaires dans les vues (disciplines et trainers). Dans le contrôleur, remplacez l'utilisation des ViewData par ce ViewModel.
Il existe déjà des fichiers .resx pour le view model RecordViewModel. Si vous utilisez un autre nom ou utilisez d'autres view models, il faudra s'assurer de faire fonctionner la traduction.
-
Dans les vues Create et Edit, remplacez les labels Trainer_Id par Trainer et Discipline_Id par Discipline
-
Dans toutes les vues, lorsque vous affichez Trainer :
- Affichez le nom complet du Trainer
-
Dans toutes les vues, lorsque vous affichez Discipline :
- Affichez le nom de la Discipline
-
Créez un service pour gérer la création des ViewModels et les interactions avec le DbContext. Attention, pour avoir tous les points vous devez utiliser la classe générique
ServiceBaseEF<>. -
Utilisez le service dans le contrôleur. Une fois que vous avez terminé, le contrôleur ne devra plus utiliser directement JulieProDBContext.
C'est le moment de tester, ajouter des commentaires et faire votre commit et votre push
Ajoutez une vue pour voir les Records d'un Trainer
- Ajoutez une action
TrainerIndexà votre contrôleur RecordController qui permet de voir les Records d'un Trainer, l'action recevra le trainerId en argument. - Ajoutez également une vue TrainerIndex pour afficher les informations. Assurez-vous qu'elle affiche les mêmes éléments que l'exemple ci-dessous.
- Dans la page d'accueil, il existe déjà une icône trophée sur le
asidedu Trainer qui vous permettra d'afficher cette page.
- Dans la page d'accueil, il existe déjà une icône trophée sur le
![]() |
|---|
- S'il n'y a pas de record associé, la vue devra afficher cela. Pour ajouter un émoji, appuyez sur les touches "Window" et ";" du clavier.
![]() |
|---|
C'est le moment de tester, ajouter des commentaires et faire votre commit et votre push
Modifiez la vue Index du contrôleur Record
Retournez voir votre laboratoire de la séance 19, nous allons utiliser DataTable pour améliorer la vue Index.
- Changez le code pour afficher la Table avec DataTable. Si ça ne marche pas allez voir les erreurs dans la console (assurez-vous de charger DataTable après jQuery dans le code).
![]() |
|---|
- Remplacez la pagination par du scrolling vertical, allez voir la documentation pour trouver le bon type de scrolling. Mettez la valeur du paramètre scrollY à 400px pour voir d'avantage de lignes.
![]() |
|---|
-
Dans votre code HTML, ajoutez un footer (
<tfoot></tfoot>) à la table avec une rangée et le bon nombre de colonnes, mais sans contenu textuel. -
À l'aide des fonctionnalités offertes par DataTables, ajoutez une recherche par sélection pour les colonnes Discipline et Trainer, allez voir la documentation pour vous aider.
Pour cibler des colonnes, la méthode column() peut avoir une liste d'indices en argument, ex : column([4,6])
![]() |
|---|
- La fonctionnalité suivante n'est pas évaluée et est difficile à réaliser, elle est seulement donnée pour ceux qui aiment les défis 💪. On veut que seulement les valeurs filtrées soient disponibles dans les listes de sélection.
Il n'est pas nécessaire d'afficher le texte --All-- dans la sélection, cet élément ne fait pas partie de la question et la case sera vide dans votre cas.
![]() |
|---|
C'est le moment de tester, ajouter des commentaires et faire votre commit et votre push
Terminez de mettre en place i18n
Ce qui est déjà fait :
- Les packages NuGet sont installés
- Les vues sont déjà traduites!
- Les modèles aussi!
- L'injection du IViewLocalizer est aussi déjà présente
Ce qu’il faut faire :
- Il faut configurer i18n dans Program.cs. Les fichiers de traduction resx se trouvent dans le répertoire ** /i18n/ **
- Il faut ajouter une fonction SetLanguage au HomeController
- Il manque le commutateur de langue dans le _Layout. Utilisez une vue partielle et nommez-la _SelectLanguage
- Finalement, il faut gérer la culture correctement en ajoutant les librairies nécessaires et en modifiant la vue partielle _ValidationScriptsPartial. (VOIR: Séance 24 et son laboratoire) (Assurez-vous que vous pouvez modifier une entrée avec un nombre avec une décimale en français et en anglais sans problème)
C'est le moment de tester, ajouter des commentaires et faire votre commit et votre push
Vérification de la traduction
- Assurez-vous que vos nouvelles pages (Records) sont toutes bien traduites
- Les resx sont généralement déjà là, utilisez-les
- N'oubliez pas de faire la traduction pour le No records
- On ne vous demande pas de faire la traduction du DataTable
- Il manque la traduction des messages d’erreur. Assurez-vous de faire la traduction pour les cas suivants:
- Une valeur de Amount invalide (Out of Range) (Modèle Record)
- Un champ Unit manquant (champ vide) (Modèle Record)
- Vous pouvez en faire plus, mais ce ne sera pas évalué. La traduction du message "must be a number" est assez complexe, alors ce n'est pas conseillé d'essayer de le traduire!
C'est le moment de tester, ajouter des commentaires et faire votre commit et votre push
Grille de correction
| Tâche | Nb Points |
|---|---|
| Filtre et surlignage des TrainerCertifications | 5 |
| Faire fonctionner le filtre de Trainer | 5 |
| Afficher le détail d'un Trainer | 1 |
| Faire fonctionner la pagination | 5 |
| Ajouter RecordController | 7 |
| Ajouter une vue pour les records d'un entraîneur | 3 |
| Modifier la vue pour l'Index des records (dataTable js) | 4 |
| Terminer de mettre en place i18n | 3 |
| Traduire le contenu ajouté | 1 |
| Commits avec textes pertinents | 1 |
| Total | /35 |








