Bonjour tous monde,

Ce que je fais

Voilà je dois pour l'un de mes projets réaliser la possiblité de faire une facture à l'aide du language JavaScript et de requêtes AJAX.

Cependant, je rencontre un petit problème, j'ai comme consigne d'avoir la possibilité de rajouter des lignes à mon tableau, chose que je fais avec une de mes méthodes, en utilisant insertRow(-1) et ensuite insertCell(...). Voici mon code ( je m'excuse d'avance pour la présentation du code, il s'agit de mon premier post tout forum confondu où je présente du code) :

</div>
<div class="tableau" id="facture">
    <table>
        <thead>
        <tr class="entete_tableau">
            <th>Code prestation</th>
            <th>Désignation</th>
            <th>Prix</th>
            <th>Quantité</th>
            <th>Montant</th>
        </tr>
        </thead>

        <tbody id="tabBody">
        <tr id="productRow">
            <td id="productCode"></td>
            <td id="productSelect">
                <select  id="products" >
               <option value="">Vide</option>

            </select></td>
            <td id="price"></td>
            <td id="amount"><input type="text" name="price" onchange="sumCalculation(this)"/> </td>
            <td id="sum"></td>
        <span id="reductionColor"></span>
        </tr>
        </tbody>
        <tfoot>
        <tr id="trSum">
            <td class="invisible"></td>
            <td class="invisible"></td>
            <td class="invisible"></td>
            <td class="titleTotale">Somme</td>
            <td  id="totalSum"></td>
        </tr>
        <tr id="trReduction">
            <td class="invisible"></td>
            <td class="invisible"><span id="colorReduction"></span></td>
            <td class="invisible"></td>
            <td > Remise</td>
            <td><span id =reduction></span> </td>
        </tr>
        <tr id="trRealTotal">
            <td class="invisible"></td>
            <td class="invisible"></td>
            <td class="invisible"></td>
            <td > A régler</td>
            <td  id="realTotal"></td>
        </tr>
        </tr>
        </tfoot>
    </table>
</div>

JS ( Les méthodes utilisés)

function showProduits(){  /*Utilisé lors du onload() du <body></body> */

    xmlhttp = new XMLHttpRequest()
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {

            var products = xmlhttp.responseText.split(";");

            for (var i = 1; i < products.length - 1; i++) {
                document.getElementById("products").innerHTML += '<option value="' + i + '" onclick="getProductDetails(' + i + ')" >' + products[i - 1] + '</option>';
            }
        }
        }
    xmlhttp.open("GET" , "getProductDetails.php",true);
    xmlhttp.send();
}
function addRows() {

    var tab = document.getElementById("tabBody");
    var row = tab.insertRow(-1);
    var rowsNumber = tab.rows.length;

    cell = row.insertCell(0);
    cell.innerHTML += "";

    cell = row.insertCell(1);
    cell.innerHTML += /*Code pour la liste déroulante */

    cell = row.insertCell(2);
    cell.innerHTML += "";

    cell = row.insertCell(3);
    cell.innerHTML += '<input id= "price'+rowsNumber+'"> </input>';

    cell = row.insertCell(4);
    cell.innerHTML += "";

}

Ce que je veux

J'aurais donc voulu savoir dans un premier temps comment pourrais-je récuperer ces données au moment ou j'ajoute une ligne. Et dans une deuxième temps si il était poible de définir des "Id" différents pour chaque 'td' crée grâce à insertCell. ( Par exemple pour ma première ligne de tableau id="price" ensuite pour la deuxième id="price2" ect..., pour avoir la possibilité de récuperer les données de chaque ligne et de chaque cellule grâce à un boucle.

Ce que j'obtiens

Petit soucis, dans l'une des cellules je dois afficher une liste déroulante avec les prestations disponible, ces prestations sont récupérer grâce à une requête SQL, prestations que je n'arrive à faire afficher que pour la première ligne du tableau mais pas pour les suivantes.

<a href="http://www.hostingpics.net/viewer.php?id=684798Capturedcran20170325161115.png"><img src="http://img4.hostingpics.net/thumbs/mini_684798Capturedcran20170325161115.png" alt="Heberger image" /></a>

Merci d'avance

20 réponses


saibe
Réponse acceptée

hello,
plusieurs solutions. soit tu te fais une variable globale idTr que tu incrémenteras au fur et à mesure de tes insert
soit mieux : tu clone un tr "model". Pour ce faire il faudra modifier le tr de ton tbody et remplacer tous les id par des class (un id doit être unique)
en gros, ton tbody ressemblera à ça :

<tbody id="tabBody">
        <tr class="productRow model"> // ici tu rajoutes la class model
            <td class="productCode"></td>
            <td class="productSelect">
             <select  class="products" >
               <option value="">Vide</option>
            </select></td>
            ...

avec le css .model{display:none;} pour le rendre invisible
tu lances ta function showProduits en modifiant ton querySelector

for (var i = 1; i < products.length - 1; i++) {
                document.querySelector("#tabBody .model .products").innerHTML +=.....
 }
 addRows(); // et on ajoute une ligne

tu auras donc un model de tr avec ton select rempli....
et enfin ta function addRows ressemblera à ça :

function addRows(){
    newTr = document.querySelector('#tabBody .model').cloneNode(true); // tu clones
    newTr.classList.remove('model'); // tu retires la class model
    document.querySelector('#tabBody').appendChild(newTr); // tu l'ajoutes à ton tbody
}

et pas besoin d'id, tu récupères tes infos avec un document.querySelectorAll('#tabBody tr')

voilà en gros l'idée...

Très bien je te remercie je vais tester ça :) !

Alors effectivement, le clonage fonctionne mieux pour afficher les différentes lignes avec la même liste, mais il y a quelque chose que je n'arrive pas à comprendre. Lorsque pour une ligne je sélectionne un produit dans un liste déroulante, avec onclick, je déclenche une fonction qui va me permettre d'afficher dans les cellules de la ligne le code du produit et son prix. Sachant que je récuperais les données avec l'id j'utilisais ensuite innerHTML pour écrire dans la balise correspondante. Avec un querySelector comment fait-on pour écrire dans certaines cellule à la ligne concerné, étant donnée que les lignes possède toutes la même classe ?

;) hello,
le principe sera, qu'une fois cloner, tu ajoutes un écouteur au sélect (donc un 'change' pas un 'click') et ensuite de récupérer le parentNode ayant le tag 'tr'. Si tu n'utilises pas de library genre jquery, il te faudra monter une tite function pour le récupérer car le parentNode de ton select est un td. Soit tu fais basique et tu récupères le parentNode du parentNode, soit (beaucoup plus élégant et efficace) tu montes une tite function récursive qui testera le tag jusqu'à l'obtention de la valeur désirée (ici tag == 'tr')... tu auras donc accès au tr et a tout ce qu'il contient...

tu comprends ? s'il y a des côtés obscurs n'hésite pas....

Salut à toi ! Déjà je te remercie pour tes réponses ;)
Alors pour être franc avec toi ça reste encore un peu vague. J'ai déjà un écouteur 'click' sur les balises option et non pas sur le selecteur, ce qui me permet de récuperer l'id du produit (fonction affiché en bas :) ). Il faudrait donc que je rajoute un écouteur 'change' sur le selecteur cette fois si, et qui va appeller la fonction me permettant de selectionner le parent du parent du select c'est bien ça ? Mais dans mon cas la fonction permettant de récuperer l'id va s'éxécuter avant la fonction permettant de récupérer le tr ? Donc je ne pourrais pas écrire dans cellules que je veux non ?
Je m'excuse si mon expression est assez confuse, l'explication n'a jamais été mon fort :).

function getProductDetails(id){
    xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {

            var productInfo = xmlhttp.responseText.split(';');

          document.getElementsById("productCode").innerHTML = productInfo[0]; // A changer car plus d'id disponible
          document.getElementsById("price").innerHTML = productInfo[1] // A changer car plus d'id disponible
        }
    }
    xmlhttp.open("GET", "getAllProductDetails.php?q="+id,true);
    xmlhttp.send();

}

;) pas de soucis, on est là pour apprendre, et dans mon cas, apprendre à comprendre... ;)
quand tu me dis :

J'ai déjà un écouteur 'click' sur les balises option

tu parles des balises option de ton select ?
si oui....... comment dire..... ce n'est pas le principe du fonctionnement d'un select.
il semblerait que tu envoie cette function function getProductDetails(id){ au click...
pourrais-je avoir un exemple html d'une balise option ?

Oui je parle de mes balises option de mon select qui sont crées grâce à la fonction ShowProduits() et qui va se charger d'ajouter des options par rapport au nombres de produits dans ma base de données:

var products = xmlhttp.responseText.split(";");

            for (var i = 1; i < products.length - 1; i++) {
document.querySelector("#tabBody .model .products").innerHTML  += '<option value="' + i + '" onclick="getProductDetails(' + i + ')" >'  + products[i - 1] + '</option>';

}

Donc mon HTML ne contient que celà concernant le select :

<td class="productSelect">
                <select  class="products" >
                    <option value="">Vide</option>
                </select>
 </td>

Préfères-tu que je t'envois tout mon code pour une meilleur compréhension ?

;) ok
donc non ! il ne faut pas faire ainsi...
un select est une balise qui peut prendre différentes valeurs en fonction de ses options. cad que si une option est "selected" alors la value de ce select est la value de cette option.... (et je ne parle pas des select multiple pour ne pas t'embrouiller...)
donc : si tu sélectionnes une option, ton select a la valeur de cette option...

suis-je clair ?

si oui, tu dois comprendre qu'un click sur une option est intrinsèque au système de select et donc qu'il est inutile de l'observer, ce que tu dois observer c'est une modification de la valeur de ton select....

suis-je encore clair ?

Oui oui je comprends tout à fait jusque là, donc inutile de mettre l'écouteur sur chaque option , le mettre sur le select suffit car il récupère la valeur de l'option selectioné

tout à fait ;)
donc tu as dû modifier ton innerHtml de ton select et ta function addRows en conséquences...
je peux voir ?

<td class="productSelect">
                <select  class="products" onchange="getProductDetails(this.value)" >
               <option value="">Vide</option>

            </select></td>
for (var i = 1; i < products.length - 1; i++) {

                document.querySelector("#tabBody .model .products").innerHTML  += '<option value="' + i + '" >' + products[i - 1] + '</option>';
            }

parfait :)
après je suis pas fan des "event dom" genre "onchange", "onclick"... mais pourquoi pas ? ....
si tu postes, c qu'il y a un nouveau soucis... lequel ?

:), il s'agit de nos premiers cours en JS donc je pense que ce sont les fondamentaux.
Il va donc falloir maintenant changer la méthode getProductDetails de sorte à qu'elle écrive dans le bon Tr, donc comme tu m'a dis tout à l'heure il faut que l'on récupère le bon parent du parent pour ensuite avoir accès à toute la ligne ?

;) c ça...
tu es étudiant ? quel niveau ?

2 ème année en DUT Informatique.

;) ok, donc je vais pas te donner une solution (sorry...) ce serait improductif (tu n'apprendrais rien...)
je pars du principe que tu n'as pas le droit d'utiliser de library tiers (genre jquery)
récupérer un parentNode c simple : il faut lire la doc ;
après, comme je te l'ai dit plus haut, tu peux faire un truc dégueulasse et récupérer le parentNode du parentNode ; ça va fonctionner dans ton cas... mais après il faut se poser les bonnes questions...

Très bien , de toute manière même si j'ai la solution j'essaie toujours de la comprendre avant de faire un copier coller betêment.
Alors il est vrai que nous avons pas encore parler de la librairie Jquery , et encore moins des noeuds ( Parent, Child ) sur javascript, même si je comprends ces différentes notions grâce au graphes.
Ils nous interdisent absolument pas d'utiliser ce que l'ont veut mais ils préfère juste question de facilité et de pédagogie, que l'on applique ce qu'ils nous ont appris .
Oui je comprend , pour te dire je partais sur un truc bien plus dégueulasse concernant l'ajout de ligne, avant que tu me parle de clonage de ligne.

"un bon codeur est une personne cultivée" c'est vrai, dommage pour moi que l'inverse ne soit pas vrai :)
"une grammaire réfléchie ? " je pense que le sujet de discussion divague, somme nous dans un cours de philosophie ?
Penses-tu réellement qu'il soit intéressant de savoir ce qu'un codeur doit où ne doit pas être ? Je laisse cette question pour les fanatiques de l'informatiqe ;).
J'ai troujours cherché à résoudre mes problèmes tout seul, en me renseignant sur les documentations et les sites qui sont à notre dispsitions.

Ce qui n'empêche pas à certain moment de rencontrer des difficultés, et par manque de temps de devoir demander une explication rapide sur le problème que l'on recontre d'où le fait qu'il sagit de mon premier post dans un forum informatique.

Merci du temps accordé, même si la solution fut partielle :)
Bonne soirée et bonne continuation.

;) on sera toujours là pour t'aider...
++