La problématique
Vous avez créé une page d’administration pour votre module, et chacun des articles a potentiellement des attributs différents. Prenons un exemple :
Pour ce type d’événement que nous voyons ci-dessus, on retrouve certains champs propres à cet événement dans l’onglet « variables de la campagne »:
Tandis que si l’on change le type d’événement dans « Information de la campagne »:
On aimerait avoir des attributs différents, qui correspondent à l’événement choisi :
Dans votre page d’édition, vous ne voudriez donc pas afficher les mêmes champs en fonction du type d’article choisi. Que faire ? afficher tous les champs ? pas très intuitif. Voici comment procéder.
Une solution
Une solution que j’ai pu mettre en place sur un module de campagne d’email EmailCampaign est de recharger les onglets et leur formulaire en Ajax, à chaque fois que l’utilisateur change le type de l’article. Par exemple, pour EmailCampaign, c’est le champ « événement » qui rendait les champs dynamiques, comme on peut le voir dans les exemples au-dessus et ci-dessous :
Lorsque l’on change celui-ci, les champs des autres onglets peuvent changer également. Il peut même y avoir des onglets différents pour chaque événement ! Sans la solution, on se retrouve dans le cas où les champs ne correspondent plus au type d’événement que l’on a, on est d’abord obligé d’enregistrer puis de re-éditer, un peu lourd quand même … Surtout lorsque des champs obligatoires n’ont plus lieu d’apparaître.
Nous allons donc voir comment mettre en place une solution !
Le contrôleur
Il nous faut créer une nouvelle action dans notre contrôleur d’administration :
public function loadFormAjaxAction() { $item = Mage::getModel('module/item'); // on sauvegarde les données post dans notre model foreach ($this->getRequest()->getParams() as $k => $param) { if (is_string($param)) { $item->setData($k, $param); } } // on l'enregistre pour que les blocs puissent l'utiliser Mage::register('item_data', $item); $block = $this->getLayout()->createBlock('module/adminhtml_item_edit_tabs'); $html = $block->toHtml(); $this->getResponse()->setHeader('Content-Type', 'application/json'); echo Zend_Json::encode(array( 'tabs' => $html, )); }
Nous allons ici chercher le bloc qui se charge de rendre les onglets. Nous chargeons aussi l’article de ses données transmises en post, cela évite aussi un load pour la base de donnée. Celui-ci servira à pré-remplir les champs des formulaires si besoin (et ne pas tout retaper lorsque les blocs sont rechargés)
Le bloc de formulaire
Vous pouvez ici récupérer les données de l’article et mettre les champs avec les bonnes valeurs par défaut. Il nous faut aussi l’url ajax de notre action (avec le token, sinon cela ne fonctionnera pas). Nous modifions la méthode _prepareForm de notre bloc de formulaire :
$fieldset->addField('loadFormAjaxUrl', 'hidden', array()); $data['loadFormAjaxUrl'] = Mage::helper("adminhtml")->getUrl('adminhtml/module/loadFormAjax/'); $form->setValues($data);
Attention aussi si vous faites des appels au bloc « head » par exemple, celui-ci n’existera pas lorsque vous ferez une requête ajax. Pensez donc à valider son existence avant de lancer une méthode dessus.
Le JavaScript
Pour que tout ça fonctionne, il nous faut maintenant ajouter notre fichier javascript afin de faire cette requête ajax. Nous pouvons maintenant récupérer dans celui-ci l’url sur laquelle nous devons appeler. Le tout en prototype histoire de n’inclure aucune autre librairie externe.
document.observe("dom:loaded", function() { var loadFormAjaxUrl = $('module_loadFormAjaxUrl'); function observe() { var tabs = $('page:left'); select.observe('change', function(event, element) { new Ajax.Request($F(loadFormAjaxUrl), { method:'get', parameters: $('edit_form').serialize(), onSuccess: function(response) { var data = response.responseText.evalJSON(); var i = 0; $$('#edit_form > div').each(function (form) { if (i++ > 0) { form.remove(); } }) tabs.update(data.tabs); observe(); } }); }); setTimeout(function(){ $('module_tabs_form_section_info').click(); }, 20); } observe(); });
Il nous faut observer l’événement « change » du select. à chaque changement, nous lançons donc la requête ajax afin de recharger les onglets et leur formulaires. Vous remarquerez que je ne supprime pas tous les formulaires, le premier étant la « form_key » obligatoire pour envoyer le formulaire, et donc sauvegarder l’article. Une fois tout ça rechargé, il nous faut observer à nouveau, car l’ancien select s’est vu remplacer par le nouveau retourné par la requête ajax. Et voilà, un rechargement en ajax dynamique dans votre admin Magento ! Vous devriez avoir quelque chose comme ceci lorsque vous changez le type :