2016-05-30 1 views
1

J'ai un problème - Je souhaite ajouter un événement .onClick à chaque cellule d'une table générée dynamiquement pendant que je le crée.javascript - donnant .onCliquez sur chaque cellule d'une table

cell.onclick = function(){     
     mouseClick(row_number,i, cell);        
    }; 

Cependant, il semble que l'événement est simplement ajouté à la dernière cellule de chaque ligne. Comment est-ce possible? Est-ce en quelque sorte écrasant les précédents? Et comment le faire fonctionner?

function drawRow(rowData, length, keys, row_number){ 
//rowData - object where the row data is stored, length-row length, keys - object with table keys stored, row_number - number of the row 
    var rowData=rowData; 
    var row = document.createElement("tr");  
    for(i=0; i<length; i++){  
     var cell = document.createElement("td"); 
     console.log("Creating event for "+i+" ."); 
     cell.onclick = function(){     
      mouseClick(row_number,i, cell);        
     }; 
     var key = keys[i];  
     var cell_text = document.createTextNode(rowData[key]);   
     cell.appendChild(cell_text); 
     row.appendChild(cell); 
    } 
    return row; 
} 
+0

Bienvenue dans le monde horriblement pratique des fermetures;) –

+0

' J'ai une portée globale (pour autant que je sache - c'est une mauvaise pratique, en passant) et 'row_number' et' cell' sont étendus aux fonctions externes, donc ils seront les mêmes pour toutes les cellules. Vous pourriez [le réparer avec une fermeture] (http://stackoverflow.com/q/750486/4642212), mais je recommanderais fortement ** la délégation d'événement ** à la place. – Xufox

+0

Cette question est une copie de celui-ci http://stackoverflow.com/questions/1451009/javascript-infamous-loop-issue Voir la réponse là pour une solution possible et une explication de javascripts infâme boucle de fermeture problème. – juan8a

Répondre

1

Vous rencontrez l'un des problèmes les plus courants en JavaScript-land.

Vos fonctions onclick ne sont pas appelées avant après que la boucle for est terminée. Lorsque la boucle for est terminée, la valeur i est celle de length. Alors seulement essayez-vous de le lire. En d'autres termes, chacun de vos callbacks dire

function() {mouseClick(row_number, i, cell} 

Au moment où vous exécutez finalement le rappel, la valeur de i est sa dernière valeur.

Si vous utilisez ES6, au lieu écrire

for (let i=0; i<length; i++) 

Le letdonne à chaque appel du bloc sa propre variables i. Dans votre code, vous avez seulement un i partagé entre toutes les cellules. C'est pourquoi toutes les cellules semblent faire la même chose!

Si vous êtes encore dans le jeu ES5, remplacer la partie intérieure de votre code avec

cell.onclick = (function (j) { 
     return function() { 
      mouseClick(row_number, j, cell); 
     }        
    })(i); 

Cela donne à chacun de vos fonctions de rappel une copie de i à chaque point de la boucle. La première fois à travers la boucle, i a une valeur de 0, et le rappel que vous obtenez est

function() {mouseClick(row_number, 0, cell} 

La deuxième itération de la boucle produit

function() {mouseClick(row_number, 1, cell} 

et ainsi de suite!

Assez cool ... mais la façon ES6 avec let fait la même chose, un peu plus joliment.

(Sinon, il y a des façons de le faire cette chose avec la méthode forEach sur les tableaux Ces assurent également les itérations de la boucle ne partagent pas la variable d'index..)

+0

Bonne réponse Ray - pensez-vous également à ajouter une solution ES5?ES6 n'est pas encore totalement supporté, et il y a une bonne chance que l'OP n'utilise pas ES6 –

+0

Merci, bonne idée. –

+0

Merci beaucoup! –