[RUBY] Si vous pensez dans votre cœur, "Remplacez l'image du produit"! À ce moment-là, l'action est terminée! ~ part4 ~

supposition

--Utilisez ruby sur les rails 6.0.0.

introduction

Ceci est le synopsis de la dernière fois (part3) . J'ai implémenté une telle chose et une telle chose sur le nouvel écran d'enregistrement en utilisant jQuery.

L'état actuel est que lorsque vous sélectionnez une image, un nouveau formulaire apparaît, et lorsque vous appuyez sur Supprimer, il disparaît. À première vue, on dirait que c'est fait, mais comme ce sont toutes des actions de js, elles disparaissent sur l'écran d'édition rechargé.

Donc, dans cette partie, ce sera un travail comme faire apparaître un nouveau formulaire sur l'écran d'édition.

Soit dit en passant, l'introduction et la procédure sont décrites en détail dans la <a href="https://qiita.com/silvercrow222/items/55aeb5d13ec2bde305db""> part1 , alors jetez un œil si vous êtes intéressé.

essayons

Il y a trois choses principales à faire.

--Affichez un nouveau formulaire sur l'écran d'édition.

Quelque chose comme ça. Je vais le faire tout de suite, mais je dois ajouter un peu au contrôleur avant de pouvoir jouer avec le fichier de vue, alors commençons à partir de là.

app/controllers/products_controller.rb


#~réduction~
  private
  def product_params
    params.require(:product).permit(:name, images_attributes: [:src, :_destroy, :id]).merge(user_id: current_user.id)
  end
#~réduction~
end

J'ai ajouté une petite description au paramètre fort. Cette _destroy est une clé qui supprime les informations du modèle enfant associé. C'est une forme inconnue, mais c'est une clé décente, alors ne vous inquiétez pas.

Maintenant, écrivons le fichier de vue.

haml:app/views/products/_form.html.haml


= form_with model: @product, local: true do |f|
  = f.text_field :name, placeholder: 'name'
  #image-box
    // ~réduction~
    - if @product.persisted?
      .group{ data: { index: @product.images.count } }
        = file_field_tag :src, name: "product[images_attributes][#{@product.images.count}][src]", class: 'file'
        .remove
Effacer
  = f.submit 'SEND'

J'ai ajouté la partie @ product.persisted?. Cela semble difficile, mais je ne fais que convertir la partie de formulaire que j'ai ajoutée dans jQuery la dernière fois au format haml. J'essaye d'afficher un nouveau formulaire.

Cela a persisté? Détermine si l'instance que vous avez utilisée a été enregistrée. Il s'agit de savoir s'il s'agit d'informations nouvelles ou déjà enregistrées. N'oubliez pas que c'est très pratique.

J'ai pu l'afficher, mais le bouton de suppression actuel ne peut pas supprimer les informations déjà enregistrées dans la base de données. Vous devez donc pouvoir le supprimer à l'aide de la clé _destroy que vous venez d'ajouter.

haml:app/views/products/_form.html.haml


= form_with model: @product, local: true do |f|
  = f.text_field :name, placeholder: 'name'
  #image-box
    = f.fields_for :images do |i|
      // ~réduction~
      - if @product.persisted?
        = i.check_box :_destroy, data: { index: i.index }, class: 'hidden'
  - if @product.persisted?
    // ~réduction~
  = f.submit 'SEND'

En dehors de la précédente, j'ai également ajouté une phrase avec persistant? À l'intérieur de la boîte d'image. Si vous cochez la case avec la touche _destroy, l'enregistrement correspondant sera supprimé de la base de données. Je ne vais pas expliquer pourquoi cela se produit (parce que je ne le comprends pas entièrement ...), mais je pense que c'est une bonne idée de se rappeler comment l'écrire comme ça.

Maintenant, le mécanisme lui-même est terminé. Cependant, il n'est pas bon qu'il y ait une case à cocher séparée du bouton de suppression, nous allons donc les lier.

app/assets/javascripts/product.js


$(function() {
  // ~réduction~
  $('.hidden').hide();
  $('#image-box').on('click', '.remove', function() {
    //Obtenez l'index unique attribué au formulaire.
    const targetIndex = $(this).parent().data('index')
    //Récupérez la case à cocher correspondant à l'index obtenu.
    const hiddenCheck = $(`input[data-index="${targetIndex}"].hidden`);
    //S'il y a une case à cocher, cochez-la.
    if (hiddenCheck) hiddenCheck.prop('checked', true);
    ~réduction~
  });
});

Traitement ajouté à l'événement de clic de l'image-box. J'ai également écrit un commentaire ligne par ligne. C'est facile à faire, donc si vous connaissez les bases de jQuery, ça va.

Vous pouvez également vérifier en appuyant sur le bouton Supprimer, donc masquons la case à cocher. Cette fois, j'ai utilisé js .hide (), mais vous pouvez définir display: none en css.

Ensuite, finalement, la couverture d'index est empêchée et la mise en œuvre est terminée.

app/assets/javascripts/product.js


$(function() {
  // ~réduction~
  let fileIndex = [1,2,3,4,5]
  lastIndex = $('.group:last').data('index');
  fileIndex.splice(0, lastIndex);
  // ~réduction~
});

Ajoutons une description à la partie définition de fileIndex. L'idée est d'obtenir le dernier index actuellement utilisé et de remplacer la valeur fileindex par cette valeur.

À propos, en ce qui concerne .splice, c'est un excellent qui vous permet de compter autant d'éléments que vous le souhaitez à partir des éléments spécifiés, puis d'ajouter des éléments également.

Cette fois, toutes les valeurs après le nombre spécifié par le premier argument sont supprimées et la valeur spécifiée par le deuxième argument est insérée. Puisqu'il y a beaucoup de choses qui peuvent être faites, il y a des parties compliquées dans l'écriture, alors veuillez regarder de plus près.

Au fait, l'implémentation de la fonction d'édition elle-même est terminée!

finalement

C'est enfin fait. C'était long.

Je pense qu'il est bon de dire que nous avons réalisé le "remplacement des images une par une" dans les spécifications. Après cela, ajoutez un aperçu de l'image pour une compréhension facile et vous avez terminé.

Vous pouvez entendre la voix du ciel en prévisualisant l'image dans l'article avant de prévisualiser l'image dans l'application, mais je m'en fiche. Je suis désolé, c'est difficile à lire.

Rendez-vous dans la prochaine partie! !!

Je souhaite implémenter une fonction d'édition des informations produit ~ part5 ~

Recommended Posts

Si vous pensez dans votre cœur, "Remplacez l'image du produit"! À ce moment-là, l'action est terminée! ~ part4 ~
Si vous souhaitez simplement exécuter vos conteneurs dans le cloud, Azure Container Instances est facile
Fonction similaire La partie bloquée pour la rendre asynchrone
[Rails] À propos de l'erreur selon laquelle l'image n'est pas affichée dans l'environnement de production