[JAVA] [Rails, JS] Comment implémenter l'affichage asynchrone des commentaires

Dans cet article, j'expliquerai comment implémenter l'affichage des commentaires de manière asynchrone.

画面収録 2020-10-06 -1.mov.gif

Détails d'implémentation

--Mise en œuvre en utilisant le canal --Afficher les commentaires de manière asynchrone

Qu'est-ce qu'une chaîne?

Qu'est-ce qu'une chaîne?

Un canal est un mécanisme côté serveur qui fournit une fonctionnalité de mise à jour immédiate. Définissez l'itinéraire des données et affichez les données envoyées sur l'écran du client.

Que pouvez-vous faire avec la chaîne?

Si vous définissez l'itinéraire des données ou écrivez du JavaScript pour afficher les données envoyées, les données envoyées peuvent être affichées de manière asynchrone.

Créer un fichier de canal

Exécutez la commande suivante dans le terminal % rails g channel comment (Entrez le nom du fichier que vous créez dans comment) Il existe plusieurs fichiers, mais cette fois, nous utiliserons les deux fichiers suivants. app/channel/comment_channel.rb Un fichier qui connecte le client et le serveur.

app/javascript/channels/comment_channel.js Il s'agit d'un fichier permettant d'afficher les données envoyées depuis le serveur sur l'écran client.

Description de comment_channel.rb

class MessageChannel < ApplicationCable::Channel
  def subscribed
    stream_from "comment_channel"
  end

  def unsubscribed
  end
end

Vous pouvez connecter le serveur et le client en écrivant stream_from" comment_channel ".

Description de comments_controller.rb

Une description du contrôleur. Étant donné que la fonction d'implémentation de commentaire qui n'est pas asynchrone est déjà terminée, les explications autres que la description liée à asynchrone sont omises.

Décrivez les données que vous souhaitez transmettre de la base de données à JS

Les données que je veux refléter dans JS cette fois sont les suivantes

Il est nécessaire de transmettre ces trois informations à JS par le contrôleur.

class CommentsController < ApplicationController
  before_action :authenticate_user!
  def create
    @comment = Comment.new(comment_params)
    @item = Item.find(params[:item_id])
    @comments = @item.comments.includes(:user).order('created_at DESC')
    if @comment.valid?
      @comment.save
            ActionCable.server.broadcast  'comment_channel', content: @comment, nickname: @comment.user.nickname, time: @comment.created_at.strftime("%Y/%m/%d %H:%M:%S"), id: @item.id
    else
      render "items/show"
    end
  end

  private
    def comment_params
    params.require(:comment).permit(:text).merge(user_id: current_user.id, item_id: params[:item_id])
    end
end

Seule la phrase suivante a été ajoutée dans cette implémentation. ActionCable.server.broadcast 'comment_channel', content: @comment, nickname: @comment.user.nickname, time: @comment.created_at.strftime("%Y/%m/%d %H:%M:%S"), id: @item.id

Puisque content, ʻuser, time et ʻid sont utilisés dans JS, je les ai définis. content Défini par @comment: text, la colonne de texte de la table Commentaire, c'est-à-dire le commentaire que vous avez entré. user Le surnom de l'utilisateur associé à @comment est récupéré. (Nous avons une association avec le commentaire et l'utilisateur.) time La colonne created_at de la table Comment. Tout paramètre de date et d'heure peut être affiché en écrivant strftime ("% Y /% m /% d% H:% M:% S "). J'ai fait référence à l'article suivant. Je ne me souviens pas de strftime (ruby) item JS doit se déclencher uniquement sur la page de l'élément que vous consultez actuellement, utilisez-le pour le déterminer.

Description de comment_channel.rb (JavaScript)

Cette fois, nous le décrirons dans la partie receive () de ʻapp / javascript / channels / comment_channel.js`.

app/javascript/channels/comment_channel.js


received(data) {
}

En écrivant «data» dans (), la valeur définie par le contrôleur peut être obtenue. «Reçu» signifie recevoir, donc lorsque vous recevez les données, exécutez le JS qui y est décrit! Cela signifie que. Maintenant, je vais décrire JS dans ceci!

Écrivez une branche conditionnelle afin que les commentaires ne puissent être affichés que sur la page d'élément actuellement ouverte.

app/javascript/channels/comment_channel.js


//Obtenez l'URL de la page actuellement ouverte
let url = window.location.href
//Sabrer(/)Extraire des éléments pour chacun
let param = url.split('/');
//Dans le cas de cette application, l'identifiant de l'élément se trouve à la toute fin de l'URL et il est défini comme paramItem.
let paramItem = param[param.length-1]
//ID de paramètre(L'identifiant contenu dans l'URL)Envoyé par le contrôleur`data.id`Déterminez si
if (paramItem == data.id) {}

Le branchement conditionnel est effectué avec l'instruction if. Ensuite, j'écrirai le contenu du processus dans la branche conditionnelle. Le contenu à décrire est

--Créer un élément div --Afficher l'élément généré sur le navigateur --Générer le texte à afficher

C'est un flux comme.

Créer un div à afficher

app/javascript/channels/comment_channel.js


    //Obtenez l'ID du div du lieu à afficher
    const comments = document.getElementById('comments');
    //Créer un div pour être identique à un fichier de vue existant
    const textElement = document.createElement('div');
    textElement.setAttribute('class', "comment-display");
    
    const topElement = document.createElement('div');
    topElement.setAttribute('class', "comment-top");

    const nameElement = document.createElement('div');
    const timeElement = document.createElement('div');

    const bottomElement = document.createElement('div');
    bottomElement.setAttribute('class', "comment-bottom");

Utilisez la méthode createElement pour créer un élément div et attribuez à chaque nom de classe requis la méthode setAttribute.

Au fait, la vue pour afficher les commentaires est la suivante

  <div id='comments'>
  </div>
  <% @comments.each do |comment| %>
    <div class='comment-display'>
      <div class='comment-top'>
        <div><%= comment.user.nickname %></div>
        <div><%= l comment.created_at %></div>
      </div>
      <div class='comment-bottom'>
        <p><%= comment.text %></p>
      </div>
    </div>
  <% end %>

J'ai généré un élément div, mais il n'est pas encore visible dans le navigateur. Affichons-le sur le navigateur et créons une relation parent-enfant.

app/javascript/channels/comment_channel.js


      //Afficher l'élément HTML généré sur le navigateur
      comments.insertBefore(textElement, comments.firstElementChild);
      textElement.appendChild(topElement);
      textElement.appendChild(bottomElement);
      topElement.appendChild(nameElement);
      topElement.appendChild(timeElement);

Utilisez la méthode insertBefire et la méthode appendChild. Parent element.insertBefore (élément à ajouter, où ajouter) Élément parent .appendChild (élément à ajouter) Ainsi insertBefire peut placer un élément n'importe où, et appendChild peut mettre un élément à la fin de la classe parent.

Si vous voulez voir un peu plus de détails, veuillez voir ci-dessous [JavaScript] Différence entre appendChild et insertBefore

Après avoir créé l'élément div, obtenons les informations à afficher.

app/javascript/channels/comment_channel.js


      const name = `${data.nickname}`;
      nameElement.innerHTML = name;
      const time = `${data.time}`;
      timeElement.innerHTML = time;
      const text = `<p>${data.content.text}</p>`;
      bottomElement.innerHTML = text;

Les informations à afficher sont mises dans chaque variable. les données sont les données pour reçues (données) {}. C'est la valeur définie dans le contrôleur. Vous avez défini respectivement «content», «nickname» et «time». Remplacez les éléments existants par innerHTML.

L'affichage est complet jusqu'à présent! Cependant, il y a deux problèmes à ce rythme.

  1. Les données s'affichent, mais le commentaire reste dans le champ de saisie du commentaire.
  2. Par défaut, HTML est conçu de telle sorte que le bouton ne peut être pressé qu'une seule fois. Résolvons ça!
Supprimer le commentaire dans le champ de saisie du commentaire après l'envoi des données

app/javascript/channels/comment_channel.js


    const newComment = document.getElementById('comment_text');
    newComment.value='';

C'est une description que l'ID du champ de saisie de commentaire est récupéré et la valeur qui s'y trouve est vidée.

Vous permet d'appuyer plusieurs fois sur le bouton de commentaire

app/javascript/channels/comment_channel.js


    const inputElement = document.querySelector('input[name="commit"]');
    inputElement.disabled = false;

Vous pouvez cliquer dessus plusieurs fois en récupérant l'attribut de nom du bouton "Commentaire" et en le définissant comme disabled = false.

La description est résumée ci-dessous.

app/javascript/channels/comment_channel.js


import consumer from "./consumer"

consumer.subscriptions.create("CommentChannel", {
  connected() {
  },

  disconnected() {
  },
  //↓ Lorsque vous recevez les données, exécutez-les.
  received(data) {
    let url = window.location.href
    let param = url.split('/');
    let paramItem = param[param.length-1]
    if (paramItem == data.id) {
      const comments = document.getElementById('comments');
      const comment = document.getElementsByClassName('comment-display');
      //Créer des éléments à utiliser
      const textElement = document.createElement('div');
      textElement.setAttribute('class', "comment-display");
      const topElement = document.createElement('div');
      topElement.setAttribute('class', "comment-top");
      const nameElement = document.createElement('div');
      const timeElement = document.createElement('div');
      const bottomElement = document.createElement('div');
      bottomElement.setAttribute('class', "comment-bottom");
      //Afficher l'élément HTML généré sur le navigateur
      comments.insertBefore(textElement, comments.firstElementChild);
      textElement.appendChild(topElement);
      textElement.appendChild(bottomElement);
      topElement.appendChild(nameElement);
      topElement.appendChild(timeElement);
      //Générer du texte à afficher
      const name = `${data.nickname}`;
      nameElement.innerHTML = name;
      const time = `${data.time}`;
      timeElement.innerHTML = time;
      const text = `<p>${data.content.text}</p>`;
      bottomElement.innerHTML = text;
      //Après avoir envoyé un commentaire, laissez le champ de commentaire vide
      const newComment = document.getElementById('comment_text');
      newComment.value='';
      //Vous permet d'appuyer plusieurs fois sur le bouton
      const inputElement = document.querySelector('input[name="commit"]');
      inputElement.disabled = false;
    }
  }
});

en conclusion

Je pensais que c'était terminé, mais au moment de la rédaction de cet article, j'ai trouvé un certain nombre d'erreurs et des descriptions peu claires. Je comprends à quel point le refactoring est important. Il peut y avoir des descriptions incorrectes, mais j'espère que cela aide quelqu'un.

Recommended Posts

[Rails, JS] Comment implémenter l'affichage asynchrone des commentaires
[Rails] Comment mettre en œuvre le scraping
[rails] Comment afficher les informations de base de données
[Rails] Comment mettre en œuvre le classement par étoiles
[Rails] Comment afficher une liste de messages par catégorie
Comment implémenter l'affichage sur une seule ligne de TextView dans le développement Android
Comment implémenter la fonctionnalité de recherche dans Rails
[Rails] Comment afficher les messages d'erreur individuellement
[Rails] Comment omettre l'affichage de la chaîne de caractères de la méthode link_to
Comment implémenter la fonctionnalité de classement dans Rails
Pour implémenter la publication d'images à l'aide de rails
Comment implémenter le traitement asynchrone dans Outsystems
[Rails] Comment utiliser video_tag pour afficher des vidéos
[Rails] Comment implémenter un test unitaire d'un modèle
Comment implémenter une fonctionnalité similaire dans Rails
Comment utiliser JQuery dans Rails 6 js.erb
Comment afficher le résultat du remplissage du formulaire
[Rails] Comment convertir l'affichage de l'heure UC en affichage de l'heure japonais
Comment désinstaller Rails
Comment régler l'heure d'affichage sur l'heure japonaise dans les rails
Comment implémenter la connexion invité en 5 minutes sur le portefeuille de rails
Comment implémenter une fonctionnalité intéressante dans Ajax avec Rails
[Java] Types de commentaires et comment les rédiger
[Rails] Comment changer le nom de colonne de la table
[Rails] Comment obtenir le contenu des paramètres forts
Résumé de la mise en œuvre des arguments par défaut en Java
[Rails] Comment afficher les images dans la vue
[Rails] Comment afficher les prévisions météo de l'adresse enregistrée en japonais en utilisant OpenWeatherMap
[rails] Comment publier des images
[Rails] Comment utiliser enum
[Rails] Comment utiliser enum
Comment rédiger un commentaire java
Comment lire les itinéraires des rails
[Java] Comment afficher les Wingdings
Comment utiliser la jonction de rails
Comment terminer le serveur de rails
Comment écrire des graines de Rails
[Rails] Comment utiliser la validation
[Rails] Comment désactiver les turbolinks
[Rails] Comment utiliser authenticate_user!
[Rails] Comment faire des graines
Comment écrire le routage Rails
[Rails] Comment installer simple_calendar
[Java] Comment implémenter le multithreading
[Rails] Comment installer reCAPTCHA
[Rails] Comment utiliser Scope
Comment afficher le champ de sélection de time_select toutes les 30 minutes
Comment afficher des graphiques dans Ruby on Rails (LazyHighChart)
[Rails 5] Comment utiliser gem gon ~ Comment passer des variables de Rails à JS ~
[Rails] Comment afficher les informations stockées dans la base de données dans la vue