Aller au contenu principal

29-8 Modification

La modification est très proche de la création, les principales différences étant:

  • L'événement doit être chargé initialement
  • Le formulaire doit être rempli avec les données de l'événement récupéré

Créer la page Edit

Créons la page Edit permettant de modifier un événement.

  1. Sous le dossier Web.Admin/Pages/Evenements -> Clic droit -> Add -> Blazor Component
  2. Choisir Page
  3. Nommer la composante Edit

Associer une route à la page

La route associée à la page sera: /evenements/{id:int}/edit. On peut définir cette dernière à l'aide de @page, tout en ajoutant le paramètre associé à bloc @code.

Snowfall.Web.Admin/Pages/Evenements/Edit.razor
@page "/evenements/{id:int}/edit"

<h1>Modifier l'événement</h1>

@code {
[Parameter]
public int Id { get; set; }
}

Ajouter un lien à partir de la page Show vers la page Edit

Dans la page Show, assurez-vous d'avoir un bouton "Modifier".

Dans Show, faites ensuite en sorte que le bouton Modifier pointe vers la page de modification:

Snowfall.Web.Admin/Pages/Evenements/Show.razor
<!-- ... -->

<div class="card-body">
<NavLink class="btn btn-primary" href="@($"/evenements/{Id}/edit")">Modifier</NavLink>
</div>

<!-- ... -->

Récupérer l'événement à modifier

Au chargement du composant, on doit récupérer le détail de l'événement à modifier via l'API (l'événement en tant que tel et la liste de villes).

Ajouter une variable pour contenir l'événement, le DTO de modification et la liste de villes

Snowfall.Web.Admin/Pages/Evenements/Edit.razor
@code {
[Parameter]
public int Id { get; set; }

private EvenementDto? _evenementDto;
private ModifierEvenementDto _modifierEvenementDto = new();
private List<VilleDto>? _villes;
}

Injecter EvenementHttpClient et VilleHttpClient dans le composant

Pour obtenir l'événement et la liste de villes, il sera nécessaire de faire appel aux deux clients pour Evenement et Ville.

Snowfall.Web.Admin/Pages/Evenements/Edit.razor
@page "/evenements/{id:int}/edit"
@using Snowfall.Application.Dtos.Evenements
@using Snowfall.Application.Dtos.Villes
@using Snowfall.Web.Admin.HttpClients
@inject EvenementHttpClient EvenementHttpClient
@inject VilleHttpClient VilleHttpClient

Récupérer l'événement et la liste de villes

Nous avons déjà les fonctions au niveaux des clients pour récupérer ces informations, il suffit d'appeler les fonctions respectives lors de l'initialisation du composant (OnInitializedAsync).

Imgur

Oops!, le code de cette portion a disparu, vous devrez la compléter vous-même!

Snowfall.Web.Admin/Pages/Evenements/Edit.razor
@code {
[Parameter]
public int Id { get; set; }

private EvenementDto? evenementDto;
private List<VilleDto>? villes;

protected override async Task OnInitializedAsync()
{
// Oups...! Le code a disparu :(
// Récupérez l'événement et la liste de villes, puis assignez-les aux variables
}
}

Mapper le DTO d'événement vers le DTO de modification

Une fois que vous aurez récupéré le DTO de l'événement, il faut le "mapper" au DTO de modification.

danger

Les étapes qui suivent sont importantes! Un moment d'égarement de ma part a mené à vous faire créer le fichier de configuration AutoMapper dans le projet Api. Or, nous avons besoin de faire du mapping dans le projet Admin. Nous allons donc déplacer le fichier de configuration AutoMapper, en plus d'installer AutoMapper dans le projet Application afin qu'il soit accessible à toute l'application.

  1. Installer AutoMapper dans Application. Dans le projet Application, click droit->Manage Nuget Packages->Recherchez AutoMapper->Procédez à l'ajout dans le projet
  2. Dans Rider, déplacez le fichier Snowfall.Web.Api/Configurations/AutoMapperConfig.cs vers le dossier Snowfall.Application/Mappings. Rider devrait faire le refactoring nécessaire.
  3. Ajoutez un mappage de EvenementDto vers ModifierEvenementDto
    Snowfall.Application/Mappings/AutoMapperConfig.cs
    public AutoMapperConfig()
    {
    CreateMap<Evenement, EvenementDto>().ReverseMap();
    CreateMap<CreerEvenementDto, Evenement>();
    CreateMap<EvenementDto, ModifierEvenementDto>();
    CreateMap<Ville, VilleDto>().ReverseMap();
    }
  4. Ajoutez AutoMapper aux services accessibles à l'injection de dépendance du projet Admin.
    Snowfall.Web.Admin/Program.cs
    // Injection de dépendances
    builder.Services.EnregistrerServices();
    builder.Services.AddAutoMapper(typeof(AutoMapperConfig));
  5. Injecter AutoMapper dans la page
    Snowfall.Web.Admin/Pages/Evenements/Edit.razor
    @page "/evenements/{id:int}/edit"
    @using AutoMapper
    @using Snowfall.Application.Dtos.Evenements
    @using Snowfall.Application.Dtos.Villes
    @using Snowfall.Web.Admin.HttpClients
    @inject EvenementHttpClient EvenementHttpClient
    @inject VilleHttpClient VilleHttpClient
    @inject IMapper Mapper
  6. Mapper EvenementDto vers ModifierEvenementDto lors de l'initialisation
    Snowfall.Web.Admin/Pages/Evenements/Edit.razor
    protected override async Task OnInitializedAsync()
    {
    (var status, _evenementDto) = await EvenementHttpClient.ObtenirEvenement(Id);
    _villes = await VilleHttpClient.OtenirVilles();

    Mapper.Map(_evenementDto, _modifierEvenementDto);
    }

Afficher un message de chargement

Pendant le bref moment où _evenementDto est null et donc qu'on attend une réponse de l'API, on peut afficher un message de chargement.

Snowfall.Web.Admin/Pages/Evenements/Edit.razor
@page "/evenements/{id:int}/edit"
@using AutoMapper
@using Snowfall.Application.Dtos.Evenements
@using Snowfall.Application.Dtos.Villes
@using Snowfall.Web.Admin.HttpClients
@inject EvenementHttpClient EvenementHttpClient
@inject VilleHttpClient VilleHttpClient
@inject IMapper Mapper

<h1>Modifier l'événement</h1>

@if (_evenementDto == null)
{
<p>Chargement...</p>
}
else
{

}

Créer les fonctions GererSubmit et Retour

Tout comme dans la création, on devra gérer l'action submit du formulaire en plus d'avoir une option annuler pour revenir en arrière.

Snowfall.Web.Admin/Pages/Evenements/Edit.razor
//...

async Task GererSubmit()
{
}

void Retour()
{

}

Afficher le formulaire

Pour cette portion, on peut, à quelques exceptions près, reprendre le formulaire de la page New et le mettre dans la portion else du bloc de chargement.

attention

Quelques modifications doivent être faites au formulaire:

  • La fonction GererSubmit n'existe pas, on devra la créer
  • La fonction Retour pour annuler n'existe pas non plus, elle sera à créer.
  1. Reprenez votre formulaire de la vue New et intégrez-le dans la vue Edit
    Snowfall.Web.Admin/Pages/Evenements/Edit.razor
    @page "/evenements/{id:int}/edit"
    @using AutoMapper
    @using Snowfall.Application.Dtos.Evenements
    @using Snowfall.Application.Dtos.Villes
    @using Snowfall.Web.Admin.HttpClients
    @inject EvenementHttpClient EvenementHttpClient
    @inject VilleHttpClient VilleHttpClient
    @inject IMapper Mapper

    <h1>Modifier l'événement</h1>

    @if (_evenementDto == null)
    {
    <p>Chargement...</p>
    }
    else
    {
    <div class="col-lg-6">
    <EditForm Model="_creerEvenementDto" OnValidSubmit="GererSubmit">
    <DataAnnotationsValidator />

    <div class="form-floating mb-3">
    <InputText id="nom" class="form-control" placeholder="Nom" @bind-Value="_creerEvenementDto.Nom"/>
    <label asp-for="nom">Nom</label>
    <ValidationMessage class="invalid-feedback" For="@(() => _creerEvenementDto.Nom)" />
    </div>

    <div class="form-floating mb-3">
    <InputTextArea id="description" rows="5" class="form-control" placeholder="Description" @bind-Value="_creerEvenementDto.Description"/>
    <label asp-for="description">Description</label>
    <ValidationMessage class="invalid-feedback" For="@(() => _creerEvenementDto.Description)" />
    </div>

    <div class="form-floating mb-3">
    <InputNumber id="capacite"
    class="form-control"
    placeholder="Capacité"
    ParsingErrorMessage="La capacité doit être un nombre"
    @bind-Value="_creerEvenementDto.Capacite"/>
    <label asp-for="capacite">Capacité</label>
    <ValidationMessage class="invalid-feedback" For="@(() => _creerEvenementDto.Capacite)" />
    </div>

    <div class="form-floating mb-3">
    <InputDate id="date" class="form-control" placeholder="Date" @bind-Value="_creerEvenementDto.Date"/>
    <label asp-for="date">Date</label>
    <ValidationMessage class="invalid-feedback" For="@(() => _creerEvenementDto.Date)" />
    </div>

    <div class="form-floating mb-3">
    <InputNumber id="prix" class="form-control" placeholder="Prix" @bind-Value="_creerEvenementDto.Prix"/>
    <label asp-for="prix">Prix</label>
    <ValidationMessage class="invalid-feedback" For="@(() => _creerEvenementDto.Prix)" />
    </div>

    <div class="form-floating mb-3">
    <InputSelect id="ville" class="form-select" @bind-Value="_creerEvenementDto.VilleId">
    <option value="">Veuillez faire une sélection</option>
    @if (villes != null)
    {
    @foreach (var ville in villes)
    {
    <option value="@ville.Id">@ville.Nom, @ville.PaysIso</option>
    }
    }
    </InputSelect>
    <label for="ville">Ville</label>
    <ValidationMessage class="invalid-feedback" For="@(() => _creerEvenementDto.VilleId)" />
    </div>

    <button type="submit" class="btn btn-primary">Sauvegarder</button>
    <button class="btn btn-secondary" @onclick="Retour">Annuler</button>
    </EditForm>
    </div>
    }
  2. Important: Assurez-vous de remplacer les références à _creerEvenementDto par _modifierEvenementDto!

Vous devriez maintenant être en mesure de naviguer vers la page de modification et voir les détails de l'événement dans le formulaire.

Imgur

Bouton Annuler (fonction Retour)

On peut compléter la fonction retour afin qu'elle redirige vers la page de détails (show).

@inject NavigationManager NavigationManager

//...

void Retour()
{
NavigationManager.NavigateTo($"/evenements/{Id}");
}

Sauvegarde de modifications

La dernière étape consiste à sauvegarder les modifications.

Créer la fonction ModifierEvenement de EvenementClient

Pour communiquer avec l'API, notre façade est EvenementHttpClient. On peut donc créer une fonction de modification qui fera une requête PATCH à l'API et retourne true ou false selon le résultat.

Imgur

info

Malheureusement, le code complet n'est pas disponible. Vous avez cependant la signature. Inspirez-vous de la fonction pour la création création, il y a des ressemblances!

Snowfall.Web.Admin/HttpClients/EvenementHttpClient.cs
/// <summary>
/// Permets de modifier un événement
/// </summary>
/// <param name="id">L'identifiant de l'événement à modifier</param>
/// <param name="modifierEvenementDto">L'événement à modifier</param>
/// <returns>Bool représentant le succès ou l'échec de la requête</returns>
public async Task<bool> ModifierEvenement(int id, ModifierEvenementDto modifierEvenementDto)
{
// Oups... à compléter!
}

Appeler le client lors de la sauvegarde

Finalement, lorsqu'on soumet le formulaire, on appelle le client Http et selon le résultat, on affiche un message.

Snowfall.Web.Admin/Pages/Evenements/Edit.razor
//...

async Task GererSubmit()
{
bool success = await EvenementHttpClient.ModifierEvenement(Id, _modifierEvenementDto);

// Gérez le cas ou success est true et success est false!
// Si true, vous voudrez faire afficher un Toast par exemple, et rediriger l'utilisateur
// Si false, vous voudrez faire afficher un message d'erreur, via un Toast ou autre mécanisme
}

//...
attention

N'oubliez pas de gérer les cas d'erreur, comme mentionné dans le commentaire!

Test

Vous devriez maintenant être en mesure de modifier un événement!

Imgur