[JAVA] [Rails] [jQuery] Empêche le bouton d'envoi d'être enfoncé jusqu'à ce que le formulaire soit rempli et sélectionné.

introduction

Cette fois, nous utiliserons jQuery pour définir le bouton d'envoi afin qu'il ne puisse pas être pressé tant que le formulaire n'est pas rempli et sélectionné.

Image complète

submitButtonJs.gif

Objectif de la rédaction de l'article

Partagez des informations et rédigez votre propre mémorandum.

But de l'introduction

Pour éviter une transmission erronée et améliorer la convivialité.

environnement

MacOS 10.15.7 ruby 2.6.5 Ruby on Rails 6.0.0

Conditions préalables

--JQuery a été installé.

Statut de rédacteur d'article

table

Untitled Diagram-ページ2 (1).png

La table User est "Poster", la table Post est "Post", la table Image est "Postée", la table Prefecture est "Prefectural data" et la table Category est "Post category".

La table Prefecture et la table Category utilisent des données de départ.

manette

Posts_controller.rb est en charge de la nouvelle fonction de publication.

posts_controller.rb


class PostsController < ApplicationController
  def new
    @post = Post.new
    @post.build_spot
    @post.images.build()
  end

  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to root_path, notice: "Le message est terminé"
    else
      flash.now[:alert] = "S'il vous plaît remplir les champs obligatoires"
      @post.images.build()
      render :new
    end
  end
  ...Une description ci-dessous est omise
  .
  .
  .
  private
  def post_params
    params.require(:post).permit(:title, :content, :prefecture_id, :category_id, images_attributes: [:id, :image, :_destroy]).merge(user_id: current_user.id)
  end

Travaillons maintenant.

①-1 Créer new.html.erb

Tout d'abord, créez le formulaire en html.

erb:new.html.erb


<%= form_with(model: @post, local: true, multipart: true) do |form| %>
  <ul class='formSpace'>
    <li class="prefecture">
      <label class="labelName" for="Prefecture">Prefecture:</label>
      <%= form.collection_select :prefecture_id, Prefecture.all, :id, :name, {include_blank: 'Veuillez sélectionner'}, {class: "prefecture__input", id: 'input01'} %>
    </li>
    <li class="category">
      <label class="labelname" for="category">Category:</label>
      <%= form.collection_select :category_id, Category.all, :id, :name, {include_blank: 'Veuillez sélectionner'}, {class: "category__input", id: 'input02'} %>
    </li>
    <li class="title">
      <label class="labelName" for="titleSpace">Title:</label>
      <%= form.text_field :title, class: 'title__input', id: "input03", placeholder: "Veuillez entrer un titre" %>
    </lil
    <li class='newImage'>
      <label class="labelName" for="imageSpace">Photo:</label>
      <div class="prevContent">
      </div>
      <div class="labelContent">
        <label class="labelBox" for="post_images_attributes_0_image">
          <div class="labelBox__text-visible">
Cliquez pour télécharger des fichiers (jusqu'à 5)
          </div>
        </label>
      </div>
      <div class="hiddenContent">
        <%= form.fields_for :images do |i| %>
          <%= i.file_field :image, class: "hiddenField", id: "post_images_attributes_0_image", name: "post[images_attributes][0][image]", type: "file" %>
          <%= i.file_field :image, class: "hiddenField", id: "post_images_attributes_1_image", name: "post[images_attributes][1][image]", type: "file" %>
          <%= i.file_field :image, class: "hiddenField", id: "post_images_attributes_2_image", name: "post[images_attributes][2][image]", type: "file" %>
          <%= i.file_field :image, class: "hiddenField", id: "post_images_attributes_3_image", name: "post[images_attributes][3][image]", type: "file" %>
          <%= i.file_field :image, class: "hiddenField", id: "post_images_attributes_4_image", name: "post[images_attributes][4][image]", type: "file" %>
        <% end %>
      </div>
    </li>
    <li class='content'>
      <label class="labelName" for="contentSpace">Content:</label>
      <%= form.text_area :content, class: 'content__input', id: "input05", placeholder: "Merci de saisir un commentaire" %>
    </li>
  </ul>
  <div class='send'>
    <%# <%= form.submit "Envoi en cours", class: 'send__btn', id: 'sending', value: "Publier" %>
    <input type='submit' id='sending' class='send__btn' value='Publier'>
  </div>
<% end %>

Puis écrivez scss.

new.scss



.formSpace {
  height: auto;
}

.labelName {
  color: #000000;
}
//Préfectures================================================================

.prefecture {
  height: auto;
  width: auto;
  margin-top: 1vh;
  font-size: 1.5vh;
  line-height: 1.5;
  color: #fff;
  &__input {
    width: auto;
    border: 1px solid #ccc;
    background-color: #fff;
    border-radius: 5px;
    text-align: center;
    color: #000000;
  }
}

//Catégorie ===============================================
.category {
  height: auto;
  width: auto;
  margin-top: 1vh;
  font-size: 1.5vh;
  line-height: 1.5;
  color: #fff;
  &__input {
    width: auto;
    border: 1px solid #ccc;
    background-color: #fff;
    border-radius: 5px;
    color: #000000;
  }
}

//Title===================================================================
.title {
  height: auto;
  width: auto;
  margin-top: 1vh;
  font-size: 1.5vh;
  line-height: 1.5;
  color: #fff;
  &__input {
    width: 30vw;
    border-radius: 5px;
    border: 1px solid #ccc;
    background-color: #fff;
    color: #000000;
    margin-left: 25px;
  }
}

//Image======================================================================

.newImage {
  display: block;
  margin: 16px auto 0;
  display: flex;
  flex-wrap: wrap;
  cursor: pointer;
}

.imageLabelName {
  color: #fff;
  margin-right: 25px;
}

.prevContent {
  display: flex;
}

.previewBox {
  height: 162px;
  width: 112px;
  margin: 0 15px 10px 0;
}

.upperBox {
  height: 112px;
  width: 100%;
  img {
    width: 112px;
    height: 112px;
  }
}

.lowerBox {
  display: flex;
  text-align: center;
}

.deleteBox {
  color: #1e90ff;
  width: 100%;
  height: 50px;
  line-height: 50px;
  background: #f5f5f5;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}

.imageDeleteBtn {
  background-color: #f5f5f5;
  line-height: 4vh;
  height: 4vh;
  width: 60px;
}

.imageDeleteBtn:hover {
  color: rgba($color: #1e90ff, $alpha: 0.7);
}

//Zone de clic du message CSS
.labelContent {
  margin-bottom: 10px;
  width: 620px;
  .labelBox {
    display: block;
    border: 1px dashed #ccc;
    position: relative;
    background: #f5f5f5;
    width: 100%;
    height: 162px;
    cursor: pointer;
    &__text-visible {
      position: absolute;
      top: 50%;
      left: 16px;
      right: 16px;
      text-align: center;
      font-size: 14px;
      line-height: 1.5;
      font-weight: bold;
      -webkit-transform: translate(0, -50%);
      transform: translate(0, -50%);
      pointer-events: none;
      white-space: pre-wrap;
      word-wrap: break-word;
    }
  }
}
//file_champ css
.hiddenContent {
  .hiddenField {
    display: none;
  }
  .hidden-checkbox {
    display: none;
  }
}

//commentaire====================================================================

.content {
  display: flex;
  height: auto;
  width: auto;
  margin-top: 5px;
  line-height: 1.5;
  font-size: 1.5vh;
  &__input {
    height: 15vh;
    width: 40vw;
    border-radius: 5px;
    color: #000000;
    border: 1px solid #ccc;
    background-color: #fff;
    margin-left: 0px;
    padding: 1vh;
  }
}


//Bouton d'envoi=========================================================================
.send {
  display: flex;
  justify-content: center;
  &__btn {
    height: 5vh;
    width: 25vw;
    margin: 50px 0;
    border-radius: 20px;
    background-color: #87cefa;
    border: none;
    box-shadow: 0 0 8px gray;
    color: #ffffff;
    line-height: 1.5;
    font-size: 2vh;
    font-weight: bold;
    -webkit-transition: all 0.3s ease;
    -moz-transition: all 0.3s ease;
    -o-transition: all 0.3s ease;
    transition: all 0.3s ease;
  }
  :hover {
    background-color: #00bfff;
  }
  .send__btn[disabled] {
    background-color: #ddd;
    cursor: not-allowed;
  }
}

Si vous faites jusqu'à présent, cela ressemblera à ce qui suit. newpageform1.png

point

Cette fois, afin de gérer l'état si le formulaire est saisi ou sélectionné en JavaScript

<%= form.collection_select :prefecture_id, Prefecture.all, :id, :name, {include_blank: 'Veuillez sélectionner'}, {class: "prefecture__input", id: 'input01'} %>

L'id est spécifié sous la forme "id:" input01 ".

De cette façon, id est spécifié pour chaque formulaire, mais cette fois, il est impossible de réutiliser l'id avec le même nom. Les identifiants sont attribués dans l'ordre sous la forme id = 'input02', id =' input03' ... (Le nom de la classe peut être unifié et réutilisé, mais cette fois, il sera omis.)

Concernant SCSS, il est décrit que la couleur du bouton est modifiée en fonction de l'état activé / désactivé du bouton (classe: send__btn). La gestion de l'état des boutons est gérée à l'aide d'une valeur appelée distabled, qui sera décrite plus loin. S'il n'est pas valide, une valeur appelée distabled sera donnée à l'élément, donc scss

.send__btn[disabled] {
  background-color: #ddd;
  cursor: not-allowed;
}

Si le bouton est désactivé, la couleur est grisée et le curseur est désactivé.

①-2 Décrivez le processus dans submit.js

Après cela, nous déterminerons si le formulaire a été saisi / sélectionné dans le fichier js et décrirons le processus pour activer / désactiver le bouton d'envoi.

Cette fois, nous l'écrirons dans un fichier appelé submit.js.

submit.js


//Empêcher le bouton d'envoi d'être enfoncé jusqu'à ce que le formulaire soit rempli et sélectionné=============================================
$(function() {
  //Désactivez d'abord le bouton d'envoi
  $('#sending').prop("disabled", true);
  
  //Lors de l'utilisation d'un champ d'entrée pour lequel "input" est défini pour id
  $("[id^= input],#post_images_attributes_0_image").change(function () {
      //Afin de définir si le champ de saisie est vide, l'état du contenu du formulaire est géré à l'aide d'une variable appelée send.
      let send = true;
      //id=input~Vérifiez les champs de saisie spécifiés comme&Vérifiez l'image (image avec numéro d'index 0)
      $("[id^= input],#post_images_attributes_0_image").each(function(index) {
        //Vérifiez le contenu (valeurs) du formulaire dans l'ordre, et si la valeur du formulaire est vide, envoyez=faux
        if ($("[id^= input],#post_images_attributes_0_image").eq(index).val() === "") {
          send = false;
        }
      });
      //Si tous les formulaires sont remplis(send =Si vrai)
      if (send) {
          //Activer le bouton d'envoi
          $('#sending').prop("disabled", false);
      }
      //Si même un formulaire est vide(send =Si faux)
      else {
          //Désactiver le bouton d'envoi
          $('#sending').prop("disabled", true);
      }
  });
});

point

Envoyer d'abord le bouton

<input type='submit' id='sending' class='send__btn' value='Publier'>

D'autre part, le bouton est désactivé en tant que prop (disabled, false).

La méthode prop a le rôle __ de définir une valeur sur l'attribut spécifié. distabled est un attribut __ qui peut invalider l'élément HTML spécifié. En l'utilisant en combinaison avec la méthode prop prop ('disabled', true)» ・ ・ ・ Disable element prop ('disabled', false)» ・ ・ ・ Activer l'élément Vous pouvez l'utiliser comme ça.

référence: méthode prop ・ ・ ・ http://js.studio-kingdom.com/jquery/attributes/prop distabled ・ ・ ・ https://persol-tech-s.co.jp/hatalabo/it_engineer/463.html#disabled

prochain,

$("[id^= input],#post_images_attributes_0_image").change(function ()

Il est décrit comme.

La description est "L'événement se déclenche lorsque les valeurs de [id ^ = entrée] et # post_images_attributes_0_image changent.

Ce à quoi je voudrais que vous fassiez attention

[id^= input]

C'est la partie de. Cela utilise la méthode de spécification utilisant les attributs de jQuery. Il y a environ quatre façons de spécifier.

Pour la "correspondance de départ", vous pouvez obtenir tous les éléments qui correspondent à la chaîne de caractères au début du nom d'attribut simplement en ajoutant "^" comme "attribut ^ = nom d'attribut".

Dans ce cas, en définissant [id ^ = input], l'élément avec id = "input01", id = "input02, ... id =" input05, c'est-à-dire l'élément nommé input dans le nom id Vous pouvez tous les obtenir.

Pour la méthode de spécification utilisant les attributs de jQuery, je me suis référé à cet article. Si vous voulez en savoir plus que la désignation du préfixe, jetez un œil.

continuer,

let send = true;

Est décrit afin de gérer l'état du formulaire à l'aide d'une variable appelée send afin de juger si le champ de saisie est vide. Si c'est vrai, cela signifie que le formulaire est complètement rempli.

$("[id^= input],#post_images_attributes_0_image").each(function(index) {
  //Vérifiez le contenu (valeurs) du formulaire dans l'ordre, et si la valeur du formulaire est vide, envoyez=faux
  if ($("[id^= input],#post_images_attributes_0_image").eq(index).val() === "") {
    send = false;
  }
});

Pour, utilisez la méthode each pour extraire les éléments dont l'id est nommé input en fonction du nombre d'éléments. Lors de la récupération, il est nécessaire de définir une fonction de rappel dans l'argument de chaque méthode, spécifiez donc "fonction (index)". En faisant cela, vous pouvez obtenir le numéro d'index et attribuer le numéro d'index à chaque élément extrait.

Dans ce cas, en tant qu'image

0 : id="input01"Des éléments de
1 : id="input02"Des éléments de
2 : id="input03"Des éléments de
3 : id="input04"Des éléments de
4 : id="input05"Des éléments de

Je pense que ça va ressembler à ça.

De plus, # post_images_attributes_0_image est également ajouté à l'objet cible. Honnêtement, Lors de la publication de plusieurs images, je ne peux pas définir et spécifier un bon identifiant, je l'ai donc ajouté ici. (J'apprécierais que vous me disiez s'il y a une autre façon de le faire!)

Après avoir récupéré le numéro d'index avec chaque méthode

if ($("[id^= input],#post_images_attributes_0_image").eq(index).val() === "") {
  send = false;
}

Passez au traitement de.

Ici, nous vérifions si le contenu du formulaire pour chacun des éléments extraits est vide. La méthode eq est utilisée pour vérifier chacun d'eux. La méthode eq filtre les éléments actuellement correspondants par numéro d'index. (site de référence de la méthode eq)

L'élément nommé input dans id est une image dans laquelle le numéro d'index est entré dans l'argument de la méthode eq dans l'ordre car les numéros d'index 0 à 4 sont attribués dans chaque méthode. (Exemple: eq (0), eq (1) ... eq (4))

Utilisez la méthode val pour obtenir la valeur du formulaire (site de référence de la méthode val)

~~ ===" " signifie que "~~ est vide".

Il valide les éléments extraits un par un et renvoie send = false si l'un des éléments a une valeur de forme vide.

Dernier

//Si tous les formulaires sont remplis(send =Si vrai)
if (send) {
  //Activer le bouton d'envoi
  $('#sending').prop("disabled", false);
}
//Si même un formulaire est vide(send =Si faux)
else {
  //Désactiver le bouton d'envoi
  $('#sending').prop("disabled", true);
}

Pour la part de Dans le cas de if (send) (signifiant si send == true), c'est-à-dire lorsque le formulaire est complètement rempli, $ ('# envoi'). Prop (" disabled ", false); Le bouton d'envoi est activé et prêt à être pressé.

Dans le cas de else (send == false), c'est-à-dire si même un formulaire est vide, le bouton d'envoi est désactivé sous la forme $ ('# envoi'). Pro (" disabled ", true); Pour rendre impossible d'appuyer sur.

①-3 terminé

C'est ça.

submitButtonJs2.gif

finalement

Comme je suis débutant, il y a encore beaucoup de parties que je ne comprends pas bien, et honnêtement, je pense qu'il y a beaucoup de prédictions d'amélioration concernant cette implémentation, alors j'apprécierais que vous me disiez s'il existe une meilleure méthode de mise en œuvre. De plus, si vous lisez cet article, je serais très heureux si vous pouviez également obtenir LGTM. Merci de votre collaboration.

Recommended Posts

[Rails] [jQuery] Empêche le bouton d'envoi d'être enfoncé jusqu'à ce que le formulaire soit rempli et sélectionné.
L'API Rails empêche boolean d'être casté arbitrairement et a passé la validation