Voici quelques conseils pour résoudre votre problème principal et améliorer le code JavaScript que vous avez posté.
Tout d'abord, la génération de nouveaux rowids localement est requis pour le scénario d'édition local. Il faut générer les nouveaux rowids sur le serveur en cas de sauvegarde des données sur le backend dans la base de données. L'implémentation typique consiste à avoir PRIMARY KEY
défini comme int IDENTITY
dans chaque table. Cela rend les identifiants uniques et fixes. La suppression d'une ligne et la création d'une nouvelle ne seront jamais interprétées comme une modification de l'ancienne ligne car la nouvelle ligne obtiendra toujours un nouvel identifiant, qui n'a jamais été utilisé auparavant (dans le tableau).
Pour bénéficier des identifiants générés côté serveur on a deux choix principaux :
- recharger la grille après chaque opération d'ajout de ligne.
- étendre la communication avec le serveur lors de l'édition afin que le serveur renvoie le nouvel identifiant, généré dans la table de la base de données, à jqGrid. On peut utiliser
aftersavefunc
rappel (pour Ajouter une nouvelle ligne uniquement) pour mettre à jour le rowid après avoir réussi à créer la ligne sur le serveur. De nombreuses implémentations standard de services RESTful renvoient des données de ligne complètes identifiant inclusif à la fois sur Ajouter ou Modifier. On peut utiliser les données à l'intérieur deaftersavefunc
rappelez et utilisez quelque chose comme$("#" + rowid).attr("id", newRowid);
pour mettre à jour la nouvelle ligne. Celui-ci a enregistré l'identifiant dans certaines colonnes supplémentaires (comme si vous utilisiez unid
caché colonne) alors il faut utilisersetCell
méthode en plus pour mettre à jour la cellule aussi.
Le premier choix est le plus simple et je vous recommande de le mettre en œuvre en premier. Seulement si le rechargement de la grille ne satisfait pas les utilisateurs, qui ajoutent de nombreuses lignes les unes après les autres, alors vous devriez écrire un peu plus de code et implémenter le second scénario.
Votre code actuel utilise inlineNav
pour les opérations d'ajout et de modification, implémentées à l'aide de l'édition en ligne, et la méthode navGrid
pour l'opération de suppression, implémentée à l'aide de l'édition de formulaire. L'édition du formulaire, y compris Delete, utilise reloadAfterSubmit: true
option par défaut. Cela signifie que la grille sera rechargée depuis le serveur (depuis url: "/RestWithDatabaseConnection/rest/fetchData"
) après la suppression de chaque ligne. Vous pouvez résoudre votre problème principal en remplaçant afterSaveFunction
à ce qui suit :
var afterSaveFunction = function () {
$(this).trigger("reloadGrid", [{current: true, fromServer: true}]);
};
L'option current
pour conserver la sélection courante après rechargement et l'option fromServer: true
n'ont de sens que si vous utilisez loadonce: true
option en plus. Vous pouvez simplement utiliser reloadGridOptions: {fromServer: true}
option de navGrid
pour forcer le rechargement des données depuis le serveur en cliquant sur le bouton Rafraîchir/Recharger de la barre de navigation. Si vous n'avez pas autant de données que vous devez afficher dans la grille (par exemple moins de 1000 lignes), alors un tel comportement serait recommandé.
Quelques conseils plus courants pour améliorer votre code :
Vous pouvez envisager d'utiliser height: "auto"
au lieu de height: 250
et de gérer la hauteur maximale de la grille en spécifiant rowNum
valeur. L'option scrollOffset: 0
sera inutile dans le cas.
Le format des données renvoyées par le serveur semble tel que vous n'implémentez pas la pagination, le tri et le filtrage côté serveur . Vous devez utiliser loadonce: true
et forceClientSorting: true
options. Le loadonce: true
informe jqGrid de sauvegarder tout les données renvoyées par le serveur localement dans data
interne paramètre. Vous pouvez à tout moment accéder au tableau en utilisant $('#grid').jqGrid("getGridParam", "data")
. La valeur de rowNum
(la valeur par défaut est 20) sera utilisé pour local pagination. Le sortname
et le sortorder
sera utilisé pour local tri. Et vous utiliserez la boîte de dialogue de recherche (ajoutée par navGrid
) ou la barre d'outils de filtrage (ajoutée par filterToolbar
) pour local recherche/filtrage. Il simplifie le code du serveur, améliore les performances de la grille du point de vue de l'utilisateur et simplifie l'interface entre le serveur et le client. Vous pouvez utiliser l'interface RESTful classique sur le serveur sans aucune extension.
Autre remarque :je vous recommande de supprimer les id
cachés inutiles colonne (name:'id', label:'id', key: true, hidden: true, ...
). Les informations sur le rowid seront enregistrées dans id
attribut des lignes (<tr>
élément) et il n'est pas nécessaire de conserver des informations en double dans le <td>
caché élément dans chaque ligne.
Il existe de nombreuses autres parties de votre code qui pourraient être améliorées. Par exemple, l'opération DELETE que vous utilisez côté serveur semble étrange. Vous utilisez mtype: 'DELETE'
, mais vous envoyez l'identifiant de la ligne supprimée à l'intérieur de body de la demande au serveur au lieu de l'ajouter à l'URL. Correspond aux standards, le HTTP DELETE ne doit contenir aucun corps . Vous pouvez utiliser l'option jqGrid formDeleting
pour spécifier toutes les options de suppression et vous pouvez définir url
paramètre comme fonction :
formDeleting: {
mtype: "DELETE",
url: function (rowid) {
return "/RestWithDatabaseConnection/rest/delete/" + rowid;
},
ajaxDelOptions: { contentType: "application/json" },
serializeDelData: function () {
return "";
}
}
Vous devez bien sûr modifier votre code serveur de /RestWithDatabaseConnection/rest/delete/
d'utiliser le même protocole de communication et d'obtenir l'identifiant de supprimé de l'URL.
Vous pouvez utiliser navOptions
paramètre de jqGrid libre pour spécifier les options de navGrid
:
navOptions: { edit: false, add: false }
(searchtext: 'Search'
et d'autres options que vous utilisez semblent avoir des valeurs par défaut et j'ai supprimé ici).
Pour se rapprocher des normes REST, on peut utiliser l'opération HTTP PUT pour l'édition de lignes et HTTP POST pour ajouter de nouvelles lignes. Vous devez implémenter différent points d'entrée pour les deux opérations sur le backend. Vous utilisez /RestWithDatabaseConnection/rest/update
déjà et vous pouvez implémenter /RestWithDatabaseConnection/rest/create
pour ajouter de nouvelles lignes. Vous pouvez utiliser le inlineEditing
suivant change par exemple pour mettre en place le scénario :
inlineNavOptions: { add: true, edit: true },
inlineEditing: {
url: function (id, editOrAdd) {
return "/RestWithDatabaseConnection/rest/" +
(editOrAdd === "edit" ? "update" : "create");
},
mtype: function (editOrAdd) {
return editOrAdd === "edit" ? "PUT" : "POST";
},
keys: true,
serializeSaveData: function (postData) {
return JSON.stringify(dataToSend);
},
aftersavefunc: function () {
$(this).trigger("reloadGrid", [{current: true, fromServer: true}]);
},
addParams: {
addRowParams: {
position: "last",
serializeSaveData: function (postData) {
var dataToSend = $.extend({}, postData);
// don't send any id in case of creating new row
// or to send `0`:
delete dataToSend.id; // or dataToSend.id = 0;
return JSON.stringify(dataToSend);
}
}
}
}