Partage
  • Partager sur Facebook
  • Partager sur Twitter

Boucle sur donnée d'un fichier php

    11 avril 2025 à 11:12:23

    Bonjour à tous,

    J'ai appris Javascript à une (lointaine) époque mais sans avoir pratiqué, j'ai plus que beaucoup perdu mes connaissance à ce sujet...

    Après avoir étudié une multitude de vos postes me voici avec un soucis pour lequel je ne trouve pas de solution depuis quelque jour et qui me bloque quelque peu.

    Mon sujet concerne une page d'auto contrôle qui servira dans l'atelier pour les différents opérateur.

    J'ai une page en php qui est alimenté via Mysql qui me permet d'afficher les différents points qui doivent être contrôlé.

    Suivant le poste il peut y avoir un seul poste comme 5 voir 6 postes.

    Dans ma page php, j'ai intégré un formulaire qui contient, entre autre, des boutons radio (OK, NOK et N/A) ainsi qu'un textarea afin de pouvoir commenter quand la réponse choisie est NOK ou N/A.

    Ce que je souhaite, c'est que quand on sélection OK, la textarea soit masqué et que quand on sélectionne NOK OU N/A alors la textarea s'affiche et qu'elle soit alors obligatoirement complétée. Chose qui fonctionne, avec du script, quand je n'ai qu'un poste à contrôler mais quand il y a plus de poste à contrôler, le 1er poste fonctionne correctement mais pas les suivant (la textare reste visible)

    Voilà, je vous ai exposé mon soucis, maintenant je vous donne les différents code que j'ai mis en place.

    le bout du code PHP en question

    /* on affiche les données sur la page */
    	foreach($tablofinal as $valeur)
    	{	
    		echo "<div id='frm'>";
    		echo "<input type='hidden' id='maVariable' value='type[$valeur[0]][val]'>";
    		echo "<textarea name='type[$valeur[0]][zone]' rows='1'>";
    		echo $valeur[0];
    		echo "</textarea>";
    		echo "</div>";
    		echo "<div id='frm'>";
    		echo "<textarea name='type[$valeur[0]][item]' rows='1'>";
    		echo $valeur[1];
    		echo "</textarea>";
    		echo "</div>";
    		echo "<div id='frm'>";
    		echo "<label>Réalisation</label><br/>";
    		echo "<input type='radio' id='ok' name='type[$valeur[0]][val]' value='OK' required><label>OK</label>";
    		echo "<input type='radio' id='nok' name='type[$valeur[0]][val]' value='NOK' required><label>NOK</label>";
    		echo "<input type='radio' id='na' name='type[$valeur[0]][val]' value='N/A' required><label>N/A</label>";
    			echo "<div id='com_frm'>";
    			echo "<label>Commentaire:</label><br/>";
    			echo "<textarea id='type[$valeur[0]][com]' name='type[$valeur[0]][com]' rows='5' cols='30' required>";
    			echo "</textarea>";
    			echo "</div>";
    		echo "</div>";

    le script que j'utilise

    <!--   Script pour Commentaire -->
    	<script>
    
    	let maVariable = document.getElementById("maVariable").value;
    	console.log(maVariable);
    	
    		document.querySelector('#com_frm').style.display = 'none';
    		//document.querySelector('#com_frm select').removeAttribute("required");
    
    		document.getElementsByName(maVariable).forEach(function (e) 
    		{
    		  e.addEventListener("click", function () 
    		  {
    			if (e.value === 'OK') 
    			{
    			  document.querySelector('#com_frm').style.display = 'none';
    			  document.querySelector('#com_frm select').removeAttribute("required");
    			}
    			else
    			{
    			  document.querySelector('#com_frm').style.display = 'block';
    			  document.querySelector('#com_frm select').setAttribute("required", "required");
    			}
    		  });
    		});
    	</script>


    Sur la page php, j'utilise une variable caché

    echo "<input type='hidden' id='maVariable' value='type[$valeur[0]][val]'>";

    que je récupère dans le script

    let maVariable = document.getElementById("maVariable").value;

    Mais visiblement, la variable est prise en compte que pour le 1er poste mais pas les suivants...

    Et là je bloque.

    En espérant avoir été suffisamment explicite vis à vis de mon soucis et si une âme charitable savait m'orienter, voir me dépanner, ça serait top.

    Merci par avance


    • Partager sur Facebook
    • Partager sur Twitter
      11 avril 2025 à 17:35:29

      Bonjour,

      un id doit être unique sur la page. Or ton php fait une boucle, donc tous tes inputs hidden ont le même id. Il faut que tu modifies ça côté php. Idem pour la div d'id "com_frm".

      • Partager sur Facebook
      • Partager sur Twitter

      Pas d'aide concernant le code par MP, le forum est là pour ça :)

        14 avril 2025 à 16:41:11

        Bonjour Lamecarlate,

        merci de t'être penché sur mon soucis.

        J'ai modifié les ID des inputs hidden ainsi que celui des div "com_frm" comme ci dessous, mais ça ne change pas grand chose à mon soucis...

        Si dès fois tu pouvais m'orienter un peu plus, ça ne serait pas pour le déplaire.

        Merci par avance.

        Coté PHP

        /* on affiche les données sur la page */
        	foreach($tablofinal as $valeur)
        	{	
        		echo "<div id='frm'>";
        		echo "<input type='hidden' id='maVariable-$valeur[0]' value='type[$valeur[0]][val]'>";
        		echo "<textarea name='type[$valeur[0]][zone]' rows='1'>";
        		echo $valeur[0];
        		echo "</textarea>";
        		echo "</div>";
        		echo "<div id='frm'>";
        		echo "<textarea name='type[$valeur[0]][item]' rows='1'>";
        		echo $valeur[1];
        		echo "</textarea>";
        		echo "</div>";
        		echo "<div id='frm'>";
        		echo "<label>Réalisation</label><br/>";
        		echo "<input type='radio' id='ok' name='type[$valeur[0]][val]' value='OK' required><label>OK</label>";
        		echo "<input type='radio' id='nok' name='type[$valeur[0]][val]' value='NOK' required><label>NOK</label>";
        		echo "<input type='radio' id='na' name='type[$valeur[0]][val]' value='N/A' required><label>N/A</label>";
        			echo "<div id='com_frm-$valeur[0]'>";
        			echo "<label>Commentaire:</label><br/>";
        			echo "<textarea id='type[$valeur[0]][com]' name='type[$valeur[0]][com]' rows='5' cols='30' required>";
        			echo "</textarea>";
        			echo "</div>";
        		echo "</div>";
        	}

        Coté Javascript

        <script>
        
        	let maVariable = document.getElementById("maVariable-$valeur[0]").value;
        	console.log(maVariable);
        	
        	document.querySelector('#com_frm-$valeur[0]').style.display = 'none';
        		document.getElementsByName(maVariable).forEach(function (e) 
        		{
        		  e.addEventListener("click", function () 
        		  {
        			if (e.value === 'OK') 
        			{
        			  document.querySelector('#com_frm-$valeur[0]').style.display = 'none';
        			  document.querySelector('#com_frm-$valeur[0] select').removeAttribute("required");
        			}
        			else
        			{
        			  document.querySelector('#com_frm-$valeur[0]').style.display = 'block';
        			  document.querySelector('#com_frm-$valeur[0] select').setAttribute("required", "required");
        			}
        		  });
        		});
        </script>




        • Partager sur Facebook
        • Partager sur Twitter
          14 avril 2025 à 18:24:58

          Hmmm. À quoi ressemble le HTML généré ? Si l'id est toujours com_frm-$valeur[0] ça ne change rien à l'affaire…

          Si tu peux nous montrer, non plus la page entière car ça ferait beaucoup, mais le résultat de deux tours de boucle par exemple, ça aiderait à comprendre.

          • Partager sur Facebook
          • Partager sur Twitter

          Pas d'aide concernant le code par MP, le forum est là pour ça :)

            14 avril 2025 à 19:22:21

            Salut

            Si ton JavaScript contient exactement maVariable-$valeur[0] dans ce que tu peux y voir depuis le navigateur, cela ne fonctionnera pas comme tu t'y attends, parce que JavaScript (effectué côté client avec le HTML généré) n'a pas connaissance des données de PHP (effectué côté serveur, donc génère le HTML).

            Plutôt qu'une boucle pour assigner des écouteurs d'événement à des éléments très précis, tu peux boucler sur les éléments ayant une classe CSS commune, et dans l'événement, deux possibilités : soit "remonter" dans l'arbre depuis l'élément cliqué pour trouver l'élément .

            <!-- HTML — j'ai enlevé les `echo "` en début de ligne et `";` en fin -->
            <input type='radio' name='type[$valeur[0]][val]' value='OK' required id='ok$valeur[0]' class="ok" />
            <label for='ok$valeur[0]'>OK</label>
            <!-- … -->
            <div id='com_frm$valeur[0]' class="com_frm">
            	<label for='type[$valeur[0]][com]'>Commentaire:</label><br />
            	<textarea name='type[$valeur[0]][com]' required id='type[$valeur[0]][com]' class='com' rows='5' cols='30'></textarea>
            </div>
            
            <!-- JavaScript -->
            document.querySelectorAll('[type="radio"]').forEach(e => {
            	const tableRow = e.target.closest('tr');
            	if (e.value === 'OK') {
            		tableRow.querySelector('.com_frm').style.display = 'none';
            		tableRow.querySelector('.com_frm textarea').required = false;
            	}
            	else {
            		tableRow.querySelector('.com_frm').style.display = 'block';
            		tableRow.querySelector('.com_frm textarea').required = true;
            	}
            });
            

            J'ai remplacé setAttribute() parce que je me souviens avoir eu joué avec entre autres pour required, et certains navigateurs me permettaient de faire deux opérations seulement, puis plus rien (genre enlever puis remettre, plus moyen d'enlever à nouveau, ou mettre et enlever, et pareil, plus moyen de remettre). Ce qu'il faut savoir, c'est que les attributs HTML sont en majeure partie là pour permettre de déterminer les valeurs initiales des propriétés correspondantes, et celles-ci sont correctement modifiables.

            N'hésite pas à poser des questions sur ce que j'ai proposé si nécessaire.

            -
            Edité par Ymox 14 avril 2025 à 19:25:25

            • Partager sur Facebook
            • Partager sur Twitter
              15 avril 2025 à 14:54:38

              Bonjour Lamecarlate, Bonjour Ymox

              Lamecarlate,

              le html généré pour 2 boucle me donne cela:

              <div id='frm'>
              	<input type='hidden' id='maVariable-GABARIT' value='type[GABARIT][val]'>
              	<textarea name='type[GABARIT][zone]' rows='1'>GABARIT</textarea>
              </div>
              <div id='frm'>
              	<textarea name='type[GABARIT][item]' rows='1'>Mise en place de la cale adaptée au modèle (Farmer, First, Roctrailer..)</textarea>
              </div>
              <div id='frm'>
              	<label>Réalisation</label>
              	<input type='radio' id='ok' name='type[GABARIT][val]' value='OK' required><label>OK</label>
              	<input type='radio' id='nok' name='type[GABARIT][val]' value='NOK' required><label>NOK</label>
              	<input type='radio' id='na' name='type[GABARIT][val]' value='N/A' required><label>N/A</label>
              	<div id='com_frm-GABARIT'>
              		<label>Commentaire:</label>
              		<textarea id='type[GABARIT][com]' name='type[GABARIT][com]' rows='5' cols='30' required></textarea>
              	</div>
              </div>
              
              <div id='frm'>
              	<input type='hidden' id='maVariable-PRE-RETOURNEMENT' value='type[PRE-RETOURNEMENT][val]'>
              	<textarea name='type[PRE-RETOURNEMENT][zone]' rows='1'>PRE-RETOURNEMENT</textarea>
              </div>
              <div id='frm'>
              	<textarea name='type[PRE-RETOURNEMENT][item]' rows='1'>Vérification du bon positionnement des palliers (Bonne côte)</textarea>
              </div>
              <div id='frm'>
              	<label>Réalisation</label>
              	<input type='radio' id='ok' name='type[PRE-RETOURNEMENT][val]' value='OK' required><label>OK</label>
              	<input type='radio' id='nok' name='type[PRE-RETOURNEMENT][val]' value='NOK' required><label>NOK</label>
              	<input type='radio' id='na' name='type[PRE-RETOURNEMENT][val]' value='N/A' required><label>N/A</label>
              	<div id='com_frm-PRE-RETOURNEMENT'>
              		<label>Commentaire:</label>
              		<textarea id='type[PRE-RETOURNEMENT][com]' name='type[PRE-RETOURNEMENT][com]' rows='5' cols='30' required></textarea>
              	</div>
              </div>

              pour ce qui est du script, j'ai cela:

              <script>
              
              let maVariable = document.getElementById("maVariable-$valeur[0]").value;
              console.log(maVariable);
              	
              	document.querySelector('#com_frm-$valeur[0]').style.display = 'none';
              
              	document.getElementsByName(maVariable).forEach(function (e) 
              	{
              		e.addEventListener("click", function () 
              		{
              			if (e.value === 'OK') 
              			{
              				document.querySelector('#com_frm-$valeur[0]').style.display = 'none';
              				document.querySelector('#com_frm-$valeur[0] select').removeAttribute("required");
              			}
              			else
              			{
              				document.querySelector('#com_frm-$valeur[0]').style.display = 'block';
              				document.querySelector('#com_frm-$valeur[0] select').setAttribute("required", "required");
              			}
              		});
              	});
              </script>

              Ymox,

              J'ai tenté de modifier mon code suivant tes directives, mais rien n'y fait.

              Le textarea est visible lors du chargement de la page (en mode requis) et que je coche OK ou n'importe quel autre bouton radio, ça ne change rien.

              pour ce qui est du fait que le script ne connait pas la valeur réellement de

               maVariable-$valeur[0]

              c'est clair car comme tu le dis la définition se fait coté serveur, c'est pour cela que je passais par un input en mode hidden.




              -
              Edité par ArnaudMonteil1 15 avril 2025 à 16:35:57

              • Partager sur Facebook
              • Partager sur Twitter
                15 avril 2025 à 18:05:56

                Alors mon JavaScript ne remplace pas l'entier du tien, mais les lignes 8 à 23 selon le message ci-dessus au moment de ce message  ;)

                Par contre, je ne sais pas pourquoi j'avais imaginé "un vrai tableau", et du coup, effectivement, cela ne fonctionnera pas :D   :honte:
                Est-ce que l'idée d'un <div class="itemRow"> autour de tous les <div id="frm"> "pour un tour de boucle"/une itération du foreach serait envisageable ? Avec cela, on pourrait effectuer quelques adaptations.

                Puisqu'on en parle, dans ce que tu as fourni, l'ID frm est encore répliqué pour chaque <div> autour des "groupes" label-champ. Tu ne sembles pas l'utiliser avec ce que tu montres, mais si cela venait à se faire, il pourrait y avoir à nouveau des surprises.

                -
                Edité par Ymox 15 avril 2025 à 18:22:28

                • Partager sur Facebook
                • Partager sur Twitter
                  16 avril 2025 à 16:21:23

                  Bonjour Ymox,

                  Pour ce qui est des DIV avec l'ID frm,

                  l'ID frm me sert uniquement pour le fichier css et la mise en forme de la page.

                  Pour ma part, je suis ouvert à chaque proposition que me pourrait me permettre de me défaire de ce soucis.. je suis tout à l'écoute de toutes suggestion.



                  -
                  Edité par ArnaudMonteil1 16 avril 2025 à 16:22:45

                  • Partager sur Facebook
                  • Partager sur Twitter
                    16 avril 2025 à 20:18:17

                    Alors si cet ID répété ne semble pas poser de problème pour le CSS, je conseillerais de vérifier que c'est bien le cas avec tous les navigateurs.

                    Pour ce qui est du script que j'ai proposé, il suffirait donc d'ajouter ce que j'ai mentionné comme <div class="itemRow"> pour englober tout ce qu'il y a dans une boucle, et remplacer dans ma précédente proposition JavaScript .closest('tr') par .closest('div.itemRow'). Attention au fait que j'ai aussi précisé que ce code remplaçait une partie seulement.
                    Aussi, s'il devait y avoir d'autres cases à cocher dans la page, on devra ajouter une petite adaptation.

                    N'oublie pas de poser des questions sur ce que tu ne comprendrais pas.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      Il y a environ 23 heures

                      Bonjour Ymox,

                      Avant tout, merci de te pencher sur mon problème.

                      J'ai donc ajouter <div class="itemRow"> au début de la boucle (ligne 4 ci dessous)

                      /* on affiche les données sur la page */
                      foreach($tablofinal as $valeur)
                      {	
                      echo "<div class='itemRow'>";
                      	echo "<div id='frm'>";
                      	echo "<input type='hidden' id='maVariable-$valeur[0]' value='type[$valeur[0]][val]'>";
                      	echo "<textarea name='type[$valeur[0]][zone]' rows='1'>";
                      	echo $valeur[0];
                      	echo "</textarea>";
                      	echo "</div>";
                      	echo "<div id='frm'>";
                      	echo "<textarea name='type[$valeur[0]][item]' rows='1'>";
                      	echo $valeur[1];
                      	echo "</textarea>";
                      	echo "</div>";
                      	echo "<div id='frm'>";
                      		echo "<label>Réalisation</label><br/>";
                      		echo "<input type='radio' name='type[$valeur[0]][val]' value='OK' required id='ok$valeur[0]' class='ok' /><label for='ok$valeur[0]'>OK</label>";
                      		echo "<input type='radio' name='type[$valeur[0]][val]' value='NOK' required id='nok$valeur[0]' class='ok' /><label for='nok$valeur[0]'>NOK</label>";
                      		echo "<input type='radio' name='type[$valeur[0]][val]' value='N/A' required id='na$valeur[0]' class='ok' /><label for='na$valeur[0]'>N/A</label>";
                      		echo "<div id='com_frm$valeur[0]' class='com_frm'>";
                      			echo "<label for='type[$valeur[0]][com]'>Commentaire:</label><br />";
                      			echo "<textarea name='type[$valeur[0]][com]' required id='type[$valeur[0]][com]' class='com' rows='5' cols='30'>";
                      			echo "</textarea>";
                      		echo "</div>";
                      	echo "</div>";
                      	echo "<br />";
                      echo "</div<";
                      }


                      Et j'ai corrigé le script suivant ce que tu me disais également

                      <!--   Script pour Commentaire -->
                      <script>
                      
                      let maVariable = document.getElementById("maVariable-$valeur[0]").value;
                      console.log(maVariable);
                      		
                      document.querySelector('com_frm$valeur[0]').style.display = 'none';
                      document.querySelectorAll('[type="radio"]').forEach(e =>
                      {
                      	const tableRow = e.target.closest('div.itemRow');
                      	if (e.value === 'OK')
                      	{
                      		tableRow.querySelector('.com_frm').style.display = 'none';
                      		tableRow.querySelector('.com_frm textarea').required = false;
                      	}
                      	else
                      	{
                      		tableRow.querySelector('.com_frm').style.display = 'block';
                      		tableRow.querySelector('.com_frm textarea').required = true;
                      	}
                      });
                      
                      </script>


                      Et malheureusement, ça ne change rien...

                      Le textarea pour les commentaire est toujours visible à l'arrivé sur la page, et que je clique sur n'importe quel bouton radio, le commentaire est toujours visible et obligatoire...

                      Du coup, ais je mis <div class="itemRow"> au bon endroit ?

                      Aurais-tu une autre idée ?

                      Merci par avance


                      -
                      Edité par ArnaudMonteil1 il y a environ 23 heures

                      • Partager sur Facebook
                      • Partager sur Twitter
                        Il y a environ 21 heures

                        ArnaudMonteil1 a écrit:

                        Le textarea pour les commentaire est toujours visible à l'arrivé sur la page

                        1. Pourquoi ne pas le masquer avec du PHP/dans le HTML ? Au moins pour l'état initial.
                        2. Est-ce que, dans ce que tu vois avec ton navigateur et notamment du fait du console.log, tu as maVariable-GABARIT ou exactement maVariable-$valeur[0] ? Dans ce dernier cas, c'est logique que le textarea ne soit pas masqué, parce que :
                          1. querySelector('com_frm$valeur[0]') n'existe pas, du fait que $valeur[0] n'est pas une variable PHP dans le code ;
                          2. malgré le point 1 : un sélecteur commençant par une lettre ASCII correspond à une balise HTML. Or, tu cherches à sélectionner un élément avec un ID, qui demande un # devant ;
                          3. outre d'autres soucis liés au fonctionnement de PHP, cela ne masquera qu'une seule zone de texte, pas toutes.

                        Peut-être que l'entier du code nous serait utile ; en l'état, je vais juste supposer que tu ne nous montres que quelques parties d'un même fichier PHP, et que du coup dans le code JavaScript montré (oui, oui), il faudrait encadrer chaque $valeur[0] (et assimilés) par <?= … ?>.
                        Mais comme dit en 3, ce n'est pas forcément la solution : une classe sur chacune de ces zones de texte, mais uniquement sur celles qui permettent le commentaire (vu qu'il y en a pour le nom aussi), serait clairement plus pratique. Et du coup, document.querySelector('.laClasse').forEach(e => { e.style.display = 'none'; }) pourrait faire l'affaire.

                        ArnaudMonteil1 a écrit:

                        Du coup, ais je mis <div class="itemRow"> au bon endroit ?

                        Oui, mais petite coquille dans la fermeture : il y a un </div< au lieu d'un </div>. Cela risque de poser problème pour les lignes après la première.

                        Et si j'avais mis un véritable écouteur d'événement, on aurait mieux >_<

                        Il faut "un niveau supplémentaire" après mon forEach — attention, il a aussi été adapté.

                        document.querySelectorAll('[type="radio"]').forEach(radio => {
                        	radio.addEventListener('click', e => {
                        		const tableRow = e.target.closest('div.itemRow');
                        		if (e.value === 'OK')
                        		{
                        			tableRow.querySelector('.com_frm').style.display = 'none';
                        			tableRow.querySelector('.com_frm textarea').required = false;
                        		}
                        		else
                        		{
                        			tableRow.querySelector('.com_frm').style.display = 'block';
                        			tableRow.querySelector('.com_frm textarea').required = true;
                        		}
                        	});
                        });

                        -
                        Edité par Ymox il y a environ 21 heures

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Boucle sur donnée d'un fichier php

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        • Editeur
                        • Markdown