2017-05-30 1 views
2

Scénario de ce que je suis en train de réaliser:Comment modifier les données reçues du serveur avant le traitement par jqGrid

  • je récupère des données à partir du serveur
  • I boucle les données et ajouter/modifier les valeurs de certains champs
  • les données sont en cours d'affichage dans une grille
  • l'utilisateur modifie localement les données
  • une fois terminé, l'utilisateur soumet la totalité des données de la grille de la serveur

Comment j'ai essayé de le réaliser:

J'ai fait une jqGrid avec loadonce:true, editurl:'clientArray' et l'édition en ligne. Dans loadComplete je boucle les données reçues du serveur et ajoute quelques valeurs. Un bouton externe est utilisé pour obtenir les données de la grille en utilisant .jqGrid('getGridParam','data') et l'envoyer au serveur.

loadComplete: function(data){ 
    for(var i=0; i<data.rows.length; i++){ 
     var row = data.rows[i]; 
     grid.jqGrid('setRowData', row.id, { 
     missingData: 'someDefaultValue' 
     }); 
    } 
} 

Problème: Les loadComplete événement se déclenche lorsque l'utilisateur modifie la page de grille ou fait une recherche. Ce qui entraîne le dépassement de toutes les données éditées par le lui. J'ai essayé d'utiliser l'événement beforeProcessing à la place, mais il ne se déclenche jamais (Edit: Cela n'a pas fonctionné lors du test avec des données locales, mais fonctionne avec loadonce). Je n'ai trouvé aucun autre événement approprié dans le documentation.

J'ai reproduit le scénario dans la démo this. Comment dois-je modifier correctement les données après l'avoir reçu du serveur et laisser l'utilisateur éditer localement, sans outrepasser ses modifications quand il change la page ou fait une recherche?

Note: J'utilise sans jqGrid 4,14

Répondre

2

On devrait utiliser beforeProcessing au lieu de loadComplete pour faire une modification dans les données chargées à partir du serveur. Le rappel est très pratique dans le scénario loadonce: true car il ne sera appelé qu'une seule fois après le chargement des données du serveur.

Il est très important de comprendre que l'on devrait essayer de réduire le nombre de changements sur DOM de la page HTML. Si vous modifiez les données avant le traitement par l'analyseur HTML, cela fonctionne très rapidement: vous changez une propriété et seule la propriété sera modifiée. De l'autre côté, la modification d'un élément sur la page HTML suit le recalcul et probablement les changements de tous les autres éléments existants sur la page. Par exemple, vous insérez un élément sur la grille. Ensuite, la position de la grille (et donc tous les autres éléments de la grille) sera modifiée. Au moins navigateur Web doit vérifier si certains changements de tous les éléments existants requis. C'est browser reflow. Il vous fait des changements d'élément HTML dans la boucle (comme l'appel de setRowData à l'intérieur de loadComplete) puis il réduit essentiellement la vitesse de la page HTML.

Encore une remarque.Je vous recommande d'utiliser le service Echo de JSFiddle (voir here) pour simuler le chargement des données du serveur. Le code correspondant pourrait être la suivante:

var i, data = [], grid = $('#grid'); 

for(i=0; i<4; i++) { 
    data.push({id:i, select1: i%3}); 
} 

grid.jqGrid({ 
    datatype: "json", 
    mtype: "POST", 
    url: "/echo/json/", 
    postData: { 
     json: JSON.stringify(data) 
    }, 
    loadonce: true, 
    forceClientSorting: true, 
    caption: 'Testing', 
    editurl: 'clientArray', 
    rowNum: 2, 
    rowList: [2, 4], 
    pager: true, 
    colModel: [ 
     {name:'select1', label: 'Server status', editable:true, edittype:'select', formatter:'select', template: "integer", editoptions:{ 
      value:'0:AAA;1:BBB;2:CCC' 
     }}, 
     {name:'select2', label: 'Local status', editable: true, edittype: 'select', formatter:'select', editoptions:{ 
      value:'0:AAA;1:BBB;2:CCC' 
     }}, 
     {name:'act', template:'actions'} 
    ], 
    inlineEditing: { 
     keys: true 
    }, 
    beforeProcessing: function(data){ 
     var i; 
     for(i=0; i<data.length; i++){ 
      data[i].select2 = 0; 
     } 
    } 
}); 

$('#b1').click(function(){ 
    $('#out').empty() 
    var i, gridData = grid.jqGrid('getGridParam','data'); 
    for(i=0; i<gridData.length; i++){ 
     out(JSON.stringify(gridData[i])); 
    } 
}); 

function out(message){ 
    $('#out').append('<p>' + message +'</p>'); 
} 

Voir modifiée démo https://jsfiddle.net/OlegKi/c09fnaca/8/. J'ai ajouté template: "integer" dans la première colonne seulement pour démontrer la conversion des données en nombres. JqGrid gratuit prend en charge le rappel convertOnSave (voir the wiki article), ce qui aide à effectuer certaines conversions lors de l'enregistrement les données locales. par exemple définit la fonction de rappel suivant (voir the lines code)

convertOnSave: function (options) { 
    var nData = options.newValue; 
    return isNaN(nData) ? nData : parseInt(nData, 10); 
} 

à la suite des données utilisées dans la première colonne sont converties en nombre au lieu de maintenir les données sous forme de chaînes.