Dans cette partie nous allons en premier lieux ajouter la fonctionnalité d’édition directement sur notre grille pour ce faite ne devons revenir sur notre ColumnModel pour redéfinir les colonnes en leur rajoutant les éditeurs (editor) adéquat pour chacune d’elle, mais avant tous nous allons déclarer un deuxièmes DataStore pour récupérer la listes des familles.
notre ColumnModel deviendra comme suit:
Nous allons définir ici la modification et l'ajout dans une même fonction, ce qui va compliquer un peut les choses mais va nous économisé énormément de code.
Pour pouvoir modifier, c’est simple, un double ou un simple click (tous dépendra de la propriété clicksToEdit) sur la ligne souhaité et elle passe en mode édition mais pour l’ajout nous aurons besoin d’ajouter un bouton ajouter à notre grille.
Les grille ExtJS nous offre la possibilité de lui ajouter une barre d’outil qui va accueillir tous les boutons dont nous aurons besoin, vous allez voir c’est très simple, mais avant tous nous aurons besoin de déclarer une variable articleAction et une class record qui aurons pour rôle : .
articleAction permet à notre fonction d’enregistrement de déterminer si il s'agit d’un ajout ou d’une modification par défaut la variable et initialisé à “Modifier” et lorsque nous cliquons sur le bouton ajout nous la mettons a jours à “Ajout”.
le record article nous permet d’initialiser le nouvel enregistrement à insérer.
Dans l’événement click du bouton (handler ) nous avons initialisé la variable articleAction et le record article.
Nous allons maintenant écrire notre fonction EnregistrerArticle qui va se charger de transmettre au serveur les données et l’action a entreprendre (ajout ou modification).
Dans la dernière ligne du code ci-dessus nous affectons à notre fonction a l’événement 'afteredit' qui se produit juste après qu'une cellule de notre grille est modifié notre fonction d’enregistrement.
nous avez terminé les modification sur notre fichier grille.js, maintenant nous allons repassé a notre contrôleur afin qu’il puisse répondre aux requête d’édition et d’ajout.
Nous pouvons dès a présent testé notre code, vous pouvez constaté qu’il est belle et bien possible de modifier et d’ajouter des enregistrement.
Nous arrivons a la fin de cette partie qui est un peut complexe,si nous avons déclarer notre clé primaire auto-incrémenté les chose serais plus simple.
Dans la prochaine et dernière partie nous verrons comment ajouter à notre grille une barre de pagination et recherche rapide,si vous avez des problèmes faire fonctionner votre grille ou des commentaires je serai ravi d’y réponde.
notre ColumnModel deviendra comme suit:
public/js/grille.js
famillesDataStore = new Ext.data.Store({ id : 'famillesDataStore', proxy : new Ext.data.HttpProxy({ url : 'index/grille', method : 'POST' }), baseParams : { gAction : "gListeFamille" }, reader : new Ext.data.JsonReader({ root : 'results', id : 'id' }, [{ name : 'id', type : 'int', mapping : 'id' }, { name : 'Libelle', type : 'string', mapping : 'Libelle' } ]), sortInfo : { field : 'Libelle', direction : "ASC" } }); articlesCols = new Ext.grid.ColumnModel([{ header : 'Ref.', allowBlank : false, readOnly : true, dataIndex : 'ref', width : 60, hidden : false, editor : new Ext.form.TextField({ // rules about editing allowBlank : false, maxLength : 9, maskRe : /([a-zA-Z0-9\s-]+)$/ }) }, { header : 'Désignation', dataIndex : 'designation', width : 200, hidden : false, editor : new Ext.form.TextField({ // rules about editing allowBlank : false, maxLength : 20, maskRe : /([a-zA-Z0-9\s]+)$/ }) // alphanumeric + spaces allowed } , { header : 'Qte', readOnly : true, dataIndex : 'Qte', width : 50, align : 'right', hidden : false, editor : new Ext.form.NumberField({ allowBlank : false, decimalSeparator : ',', allowDecimals : true, allowNegative : false, blankText : '0', maxLength : 4 }) }, { header : 'Prix', readOnly : true, dataIndex : 'Prix', width : 80, hidden : false, renderer : Ext.util.Format.formatNumber .createDelegate(Ext.util.Format), align : 'right', editor : new Ext.form.NumberField({ allowBlank : false, decimalSeparator : ',', allowDecimals : true, allowNegative : false, blankText : '0', maxLength : 11 }) }, { header : 'Id Famille', readOnly : true, dataIndex : 'famille', width : 50, align : 'right', hidden : true, editor : new Ext.form.NumberField({ allowBlank : false, allowDecimals : false, blankText : '0', maxLength : 4 }) }, { header : 'Familles', dataIndex : 'LibFamille', width : 150, editor : new Ext.form.ComboBox({ store : famillesDataStore, typeAhead : true, triggerAction : 'all', mode : 'remote', displayField : 'Libelle', listeners : { select : { fn : function(e, rec) { var sm = articlesListGrid .getSelectionModel() .getSelected(); sm.set('famille', rec.id); } } }, listClass : 'x-combo-list-small'// , }) }, { header : 'Date d\'entrée', readOnly : true, dataIndex : 'date_ent', width : 80, hidden : false, renderer : Ext.util.Format.dateRenderer('d/m/Y'), editor : new Ext.form.DateField({ format : 'd/m/Y' }) }]); articlesListGrid = new Ext.grid.EditorGridPanel({ id : 'articlesListGrid', title : 'liste des employe', store : articlesDataStore, width : 700, height : 350, cm : articlesCols, frame : true, clicksToEdit : 1, enableColLock : false, selModel : new Ext.grid.RowSelectionModel({ singleSelect : true }), tbar : [{ text : 'Ajouter', handler : function() { articleAction = 'gAjouter'; var p = new article({ ref : '', designation : '', Qte : '0', Prix : '0', date_ent : (new Date()).clearTime(), famille : '0' }); articlesListGrid.stopEditing(); articlesCols.setEditable(0, true); articlesDataStore.insert(0, p); articlesListGrid.startEditing(0, 0); } }] });
Pour pouvoir modifier, c’est simple, un double ou un simple click (tous dépendra de la propriété clicksToEdit) sur la ligne souhaité et elle passe en mode édition mais pour l’ajout nous aurons besoin d’ajouter un bouton ajouter à notre grille.
Les grille ExtJS nous offre la possibilité de lui ajouter une barre d’outil qui va accueillir tous les boutons dont nous aurons besoin, vous allez voir c’est très simple, mais avant tous nous aurons besoin de déclarer une variable articleAction et une class record qui aurons pour rôle : .
articleAction permet à notre fonction d’enregistrement de déterminer si il s'agit d’un ajout ou d’une modification par défaut la variable et initialisé à “Modifier” et lorsque nous cliquons sur le bouton ajout nous la mettons a jours à “Ajout”.
le record article nous permet d’initialiser le nouvel enregistrement à insérer.
public/js/grille.js
// déclaration et initialisation articleAction. var articleAction = 'Modifier'; // déclaration de la classs record. var article = Ext.data.Record.create([ // the "name" below matches the tag name to read, except "availDate" // which is mapped to the tag "availability" { name : 'ref', type : 'string' }, { name : 'designation', type : 'string' }, { name : 'Qte', type : 'int' }, { name : 'Prix', type : 'float' }, { name : 'LibFamille', type : 'date', dateFormat : 'd/m/Y' }, { name : 'date_ent', type : 'date' }]); .... .... selModel : new Ext.grid.RowSelectionModel({ singleSelect : false }), tbar : [{ text : 'Ajouter', iconCls:'ajout' handler : function() { articleAction = 'gAjouter'; var p = new article({ ref : '', designation : '', Qte : '0', Prix : '0', date_ent : (new Date()).clearTime(), famille : '0' }); articlesListGrid.stopEditing(); articlesCols.setEditable(0, true); articlesDataStore.insert(0, p); articlesListGrid.startEditing(0, 0); } }] });
Nous allons maintenant écrire notre fonction EnregistrerArticle qui va se charger de transmettre au serveur les données et l’action a entreprendre (ajout ou modification).
public/js/grille.js
function EnregistrerArticle(e) { Ext.Ajax.request({ waitMsg : 'Enregistrement en cours...', url : 'index/grille', params : { gAction : articleAction, ref : e.record.data.ref, designation : e.record.data.designation, Qte : e.record.data.Qte, Prix : e.record.data.Prix, famille : e.record.data.famille, date_ent : e.record.data.date_ent.format('Y-m-d') }, success : function(response) { var result = eval(response.responseText); switch (result) { case 1 : articlesDataStore.commitChanges(); articlesDataStore.reload(); articleAction = 'Modifier'; // reload our datastore. break; case 2 : Ext.MessageBox.alert('un article du même code exist déja !'); break; default : Ext.MessageBox.alert('les données ne sont pas enregistré...'); break; } }, failure : function(response) { var result = response.responseText; Ext.MessageBox.alert('Erreur',result); } }); } articlesListGrid.on('afteredit', EnregistrerArticle);
nous avez terminé les modification sur notre fichier grille.js, maintenant nous allons repassé a notre contrôleur afin qu’il puisse répondre aux requête d’édition et d’ajout.
Application/controllers/index.php
case "gListeFamille" : $famille = new familles(); $resultat = $famille->fetchAll()->toArray(); break; case "gAjouter" : $article = new Articles (); $id = $formData['ref']; $row = ($article->find($id)); if (empty($row['ref'])) { unset($formData['gAction']); $article->insert($formData); $resultat = 1; } else {$resultat = 2;} // un Article du meme code exist déja // $resultat = ..... break; case "gModifier" : $article = new Articles (); $id = $formData['ref']; $row = ($article->find($id)); unset($formData['ref']); unset($formData['gAction']); $where = $article->getAdapter()->quoteInto('ref = ?', $id); $article->update($formData,$where); $resultat = 2; break;
Nous arrivons a la fin de cette partie qui est un peut complexe,si nous avons déclarer notre clé primaire auto-incrémenté les chose serais plus simple.
Dans la prochaine et dernière partie nous verrons comment ajouter à notre grille une barre de pagination et recherche rapide,si vous avez des problèmes faire fonctionner votre grille ou des commentaires je serai ravi d’y réponde.
Bonjour,
RépondreSupprimerEncore merci pour ce tuto qui est toujours très instructif.
Cependant, je rencontre quelques difficultés pour faire fonctionner cette troisième partie. J'ai détecté quelques incohérences, peut-être pouvez vous m'aider sur ces points. Dans le Ext.grid.ColumnModel, pour le header 'Familles' on utilise famillesDataStore qui n'est pas défini.
Dans le controller, gAjouter ou Modifier, je ne comprend pas l'utilisation de $formData['ref']. Comment fonctionne ce mécanisme? Faut-il mettre à jour la classe Articles?
Sous IE, il y a des petits problèmes de compatibilités dus à des virgules en trop.
Encore merci pour votre aide.
oui vous avez vu juste j'ai oublier d'insérer la définition du famillesDataStore, je viens de le faire et j'ai ajouter aussi le case gListeFamille l'action de notre controlleur.
RépondreSupprimer$formData['ref']et la clé primaire de notre table article, on devra vérifier sont existance avant de faire un ajout.
le fonctionnement de mécanisme est simple:
notre formulaire envoi au serveur les valeur de nos champs et quelques paramètres supplémentaires que nous récupérons sous forme de tableau comme ceci
$formData = $this->_request->getPost();.
et une fois que nous avons terminé avec les paramètres dont nous avons plus besoin nous les supprimons avant d’envoyer notre tableaux a notre base de données.
exemple: pour le cas d’une modification nous n’avons pas besoin de mettre a jours la colonne ref.
unset($formData['ref']);
unset($formData['gAction']);
Bonjour,
RépondreSupprimerMerci pour vos réponses. J'ai effectué les modifications suivantes pour que ça fonctionne correctement chez moi:
Pour le controlleur d'action "gListeFamille", j'ai dû le modifier pour obtenir une réponse json:
case "gListeFamille" :
$famille = new familles();
$rows = $famille->fetchAll()->toArray();
$data['results'] = $rows;
$resultat = Zend_Json :: encode($data);
break;
J'ai rencontré également un autre problème : Qunad je rajoute un nouveau produit, après la mise à jour (afteredit), le nouveau produit n'apparait pas dans la grid. En fait ça vient du fait qu e l'on donne 0 comme valeur par défaut à l'attribut famille.
J'ai donc rajouté dans la table Famille une nouvelle entrée:
id=5 => Libelle=Non Defini.
Dans grille.js, j'initialise l'attribut Famille par défaut avec la valeur 5 au lieu de 0 comme suit:
var p = new article({
ref : '',
designation : '',
Qte : '0',
Prix : '0',
date_ent : (new Date()).clearTime(),
famille : '5'
});
Ainsi, dés la fin de la première édition, la famille du nouveau produit devient de type Non défini.
J'espère que j'ai été assez clair.
Encore merci.
Super tuto !!
RépondreSupprimerContinues comme ça. J'attends avec impatience la suite de celui ci !
Bonjour je suis ton tuto et je le trouve tres interessant,je suis entrain de developper une application pareille mais je bloque au niveau de la fonction recherche!!en fait je voudrais faire une recherche et que le resultat apparaissent dans la mme grille!!
RépondreSupprimerdonc j'attend avec impatience la 4eme partie ou bien si vous pouvez me guider dans ma recherche.
merci et courage pour le bon boulot que vous etes entrain de faire.
Bonjour, La 4eme partie ? Merci de ton boulot Mr Idir.
RépondreSupprimerbonjour , je cherche toujours la 4ieme partie trés importante, pourriez vous me passez le lien de cette partie si elle existe.
RépondreSupprimermerci bien