Aller au contenu principal

19-8 Afficher la liste de questions

Imaginons qu'il est possible pour un utilisateur de voir la liste de questions qu'il a déjà posée pour un événement afin de modifier ou supprimer une question.

Nous allons afficher la liste de questions dans la vue New. Alors, quand un utilisateur cliquera sur poser une question, il verra par la même occasion ses questions posées précédemment pour l'événement en question.

Pour cela, il nous faut des fonctions de Repository et de Service!

Ajouter FindByEvenementIdAndUserId dans QuestionRepository

  1. Ajoutez à l'interface IQuestioneRepository une signature de fonction pour FindByEvenementIdAndUserId
    Snowfall.Data/Repositories/IQuestionRepository.cs
    public interface IQuestionRepository
    {
    Task<List<Question>> FindByEvenementIdAndUserId(int evenementId, string userId);
    Task<Question> Create(Question question);
    }
  2. Dans QuestionRepository, vous pourrez utiliser l'aide contextuelle (à la ligne du nom de la classe qui sera surligné en rouge) pour faire Implement missing members. Cela ajoutera la définition de la fonction:
    Snowfall.Data/Repositories/QuestionRepository.cs
    public async Task<List<Question>> FindByEvenementIdAndUserId(int evenementId, string userId)
    {
    throw new NotImplementedException();
    }
  3. On fait une requête pour filtrer les questions et les classer par date de création descendante.
    Snowfall.Data/Repositories/QuestionRepository.cs
    public async Task<List<Question>> FindByEvenementIdAndUserId(int evenementId, string userId)
    {
    string sql = @"
    SELECT * FROM questions q
    WHERE q.evenement_id = @EvenementId
    AND q.utilisateur_id = @UserId
    ORDER BY created_at DESC
    ";

    using (IDbConnection connection = _dbContext.CreateConnection())
    {
    var param = new
    {
    EvenementId = evenementId,
    UserId = userId
    };
    IEnumerable<Question> questions = await connection.QueryAsync<Question>(sql, param);
    return questions.ToList();
    }
    }

Ajouter FindByEvenementIdAndUserId dans QuestionService

  1. Ajoutez à l'interface IQuestionService une signature de fonction pour FindByEvenementIdAndUserId
    Snowfall.Application/Services/IQuestionService.cs
    public interface IQuestionService
    {
    Task<List<Question>> FindByEvenementIdAndUserId(int evenementId, string userId);
    Task<Question> Create(Question question);
    }
  2. Dans QuestionService, vous pourrez utiliser l'aide contextuelle (à la ligne du nom de la classe qui sera surligné en rouge) pour faire Implement missing members. Cela ajoutera la définition de la fonction:
    Snowfall.Application/Services/QuestionService.cs
    public async Task<List<Question>> FindByEvenementIdAndUserId(int evenementId, string userId)
    {
    throw new NotImplementedException();
    }
  3. Finalement, on appelle le repository à partir du service.
    Snowfall.Application/Services/QuestionService.cs
    public async Task<List<Question>> FindByEvenementIdAndUserId(int evenementId, string userId)
    {
    return await _questionRepository.FindByEvenementIdAndUserId(evenementId, userId);
    }

Créer une action Index pour afficher les questions existantes

Pour afficher les questions existantes, nous créerons une vue et une action Index. De plus, créons un ViewModel QuestionsIndexViewModel qui contiendra l'événement et la liste de questions.

  1. Créez le ViewModel QuestionsIndexViewModel
    Snowfall.Web.Mvc/Models/Questions/QuestionsIndexViewModel.cs
    public class QuestionsIndexViewModel
    {
    public required Evenement Evenement { get; set; }
    public required List<Question> Questions { get; set; }
    }
  2. Créez la signature de l'action Index
    Snowfall.Web.Mvc/Controllers/QuestionsController.cs
    [HttpGet] //GET /evenements/{evenementId}/questions
    [Authorize]
    public async Task<IActionResult> Index(int evenementId)
    {

    }
  3. Créez une vue Index sous le dossier Views/Questions qui accepte un le ViewModel créé précédemment.
    Snowfall.Web.Mvc/Views/Questions/Index.cshtml
    @model Snowfall.Web.Mvc.Models.Questions.QuestionsIndexViewModel

    @{
    ViewBag.Title = "Vos questions";
    }

    <h2>Vos questions pour l'évémement @Model.Evenement.Nom</h2>
  4. Obtenir l'événement dans l'action Index du contrôleur
    Snowfall.Web.Mvc/Controllers/QuestionsController.cs
    public async Task<IActionResult> Index(int evenementId)
    {
    var evenement = await _evenementService.FindById(evenementId);
    if (evenement == null) return NotFound();
    }
  5. Obtenir la liste de questions de l'utilisateur
    public async Task<IActionResult> Index(int evenementId)
    {
    var evenement = await _evenementService.FindById(evenementId);
    if (evenement == null) return NotFound();

    var questions = await _questionService.FindByEvenementIdAndUserId(
    evenementId,
    User.Identity!.Id());
    }
  6. Retourner le ViewModel à la vue.
    Snowfall.Web.Mvc/Controllers/QuestionsController.cs
    public async Task<IActionResult> Index(int evenementId)
    {
    var evenement = await _evenementService.FindById(evenementId);
    if (evenement == null) return NotFound();

    var questions = await _questionService.FindByEvenementIdAndUserId(
    evenementId,
    User.Identity!.Id());

    var viewModel = new QuestionsIndexViewModel()
    {
    Evenement = evenement,
    Questions = questions
    };

    return View(viewModel);
    }

Faire un lien vers la liste des questions de l'utilisateur

OK, on a une ébauche de vue et une action de contrôleur pour afficher une liste de questions pour un événement en particulier!

Sur la vue New on affichera un lien permettant à l'utilisateur d'afficher sa liste de questions.

  1. Dans la vue New afficher un lien vers la vue Index
    Snowfall.Web.Mvc/Views/Questions/New.cshtml
    <div class="row">
    <div class="col-md-6 offset-md-3">
    <h1>@ViewBag.Title</h1>

    <div class="mb-3">
    Déjà posé une question?
    <a asp-controller="Questions"
    asp-action="Index"
    asp-route-evenementId="@Model.EvenementId">Voir vos questions pour cet événement</a>.
    </div>

    <!-- ... -->

Maintenant, testez votre application pour valider que la séquence fonctionne. Aucune question ne sera affichée dans la vue, mais la séquence de navigation devrait fonctionner.

http://localhost:4200

Afficher la liste de questions

Finalement, affichez la liste de questions dans la vue!

Snowfall.Web.Mvc/Views/Questions/Index.cshtml
<!-- ... -->

<h2>Vos questions pour l'évémement @Model.Evenement.Nom</h2>

<div class="row">
<div class="col-12 col-lg-6">
@foreach (Question question in Model.Questions)
{
<div class="card mb-3">
<div class="card-body">
<p class="card-text" style="white-space: pre-line">@question.Contenu</p>
</div>
</div>
}
</div>
</div>

Ce qui devrait vous donner quelque chose comme ceci pour un événement pour lequel vous avez des questions.

http://localhost:4200

party cat

info

À noter qu'il serait préférable de créer une vue partielle pour chaque élément de la liste, mais par souci de limiter les étapes dans ce niveau, les éléments sont directement dans la vue index.