Jump to content

Paramètre champs en fonction d'un autre dans admin controller module


Recommended Posts

Bonjour,

Voilà, j'ai un module avec un formulaire en admin permettant de choisir un client via un input (recherche ajax et autocomplete).

Une fois le client sélectionné je souhaite avoir un champs juste après qui propose un dropdown avec ses références de commande.

Comment puis-je faire pour conditionner la liste déroulante sur le choix de l'input précédent ? Sachant que je récupère l'id du customer dans un attribut name une fois qu'il est choisi.

Je vous remercie.

Capture d’écran 2022-04-26 à 11.58.25.png

Link to comment
Share on other sites

D’accord je comprends le principe.

je dois transmettre ma variable à mon ModuleAdminController.

comment je peux faire pour la récupérer quand je suis dans ce controller ?

dois passer par une méthode ?

Link to comment
Share on other sites

J'ai fait ceci :

$('#customer_autocomplete_input').on('focusout', function(){
        if($('#inputCustomer').attr('value')){
            let id_customer_selected = $('#inputCustomer').attr('value');
            
            $.ajax({
                type: 'POST',
                dataType: 'json',
                url: ???, // Url vers l'admin controller
                cache: false,
                data: {
                    ajax: 1,
                    controller: 'AdminModule',
                    action: 'getcustomerid',
                    'id_customer_selected' : id_customer_selected,
                    token: '{$token}'
                },
                success: function (data) {
                    var data = jQuery.parseJSON(data);
                    id_customer_selected = data.id_customer_selected;
                    console.log(id_customer_selected);
                },
                error: function() {
                    console.log('Erreur lors de l\'envoi ajax');
                }
            })
            console.log(id_customer_selected);
        }
    });

Le seul soucis c'est que je ne sais pas comment récupérer dynamiquement l'url vers l'admin controller.

Avez-vous une suggestion svp ?

Merci

Link to comment
Share on other sites

Depuis le php de votre module qui appelle ce js, affectez la variable Smarty au tpl concerné

$ajax_link = $this->getModuleLink('NomDeVotreModule', 'NomDeVotreController', array(), Configuration::get('PS_SSL_ENABLED'));
$this->smarty->assign('ajax_link', $ajax_link);

et dans le tpl vous assignez cette variable Smarty en variable JS accessible depuis votre script

{addJsDef ajax_link=$ajax_link|escape:'quotes':'UTF-8'}

La variable JS ajax_link est à présent dispo dans votre script

Link to comment
Share on other sites

Ok je comprends, cependant le tpl en question c'est le renderForm() de mon adminController.

Est-ce que je peux utiliser ceci ? Et où dois-je le mettre dans mon adminController svp ? :

 

// Create a link with the path

$ajax_link = $this->context->link->getAdminLink('AdminController');

//define js value to use in ajax url

Media::addJsDef(array(

"ajax_link" => $ajax_link

));

 

Edited by GBPro (see edit history)
Link to comment
Share on other sites

D'accord.

Bon maintenant le soucis c'est quand regardant ce qu'il envoie (data), je constate qu'il envoi toute une page html ... Et quand je spécifie dataType: 'json' l'envoi échoue.

$.ajax({
                method: 'POST',
                url: ajax_link,
                cache: false,
                contentType: "application/json",
                processData: false,
                data: id_customer_selected,
                success: function (data) {
                    console.log('Envoi réussi : ' + data);
                },
                error: function() {
                    console.log('Erreur lors de l\'envoi ajax');
                }
            })

Je ne comprends pas pourquoi data correspond à tout une page html et pas id_customer_selected.

 

Link to comment
Share on other sites

ça ne fonctionne pas...

quand je fais : 

$.ajax({
                method: 'POST',
                url: ajax_link,
                cache: 'false',
                dataType: 'json',
                data: 'id_customer='+id_customer_selected,
                success: function (data) {
                    console.log('Envoi réussi : ' + data);
                },
                error: function(data) {
                    console.log('Erreur lors de l\'envoi ajax : ' + data);
                }
            })

La requête ajax échoue et ça me retourne comme data : [object Object]

Link to comment
Share on other sites

Je commence un peu à être perdu.

Dans mon formulaire du adminController généré via renderForm je récupère bien l'id_customer en javascript quand je sélectionne le client.

Mais ensuite je n'arrive pas à envoyer cet id_customer de nouveau au adminController pour charger les options de la liste déroulante qui vient après, avec la liste de ses commandes.

Je n'arrive pas à faire la bonne requête ajax pour renvoyer l'id au controller et je ne sais pas comment récupérer cet id dans le controller.

Dois-je appeler une méthode au niveau des data de la requête ajax ?

Capture d’écran 2022-04-27 à 13.31.32.png

Link to comment
Share on other sites

Dans votre controller, ajoutez cette fonction:

	public function ajaxProcessLoadOrders()
	{
		$id_customer = (int)Tools::getValue('id_customer');
		// Votre fonction pour récupérer les commandes
		$orders = ....

		$this->context->smarty->assign(
			array(
				'orders' => $orders,
				'link' => $this->context->link
			)
		);

		die($this->module->display(_PS_MODULE_DIR_.$this->module->name.DIRECTORY_SEPARATOR.$this->module->name.'.php', 'order-list.tpl'));
	}

Elle va se déclencher lors de l'appel de votre js (auquel je rajoute l'action)

$.ajax({
	method: 'POST',
	url: ajax_link,
	cache: 'false',
	dataType: 'json',
	data: {
		ajax: true,
		action: 'loadorders',
		id_customer: id_customer_selected
	},
	success: function (data) {
		console.log('Envoi réussi : ' + data);
	},
	error: function(data) {
		console.log('Erreur lors de l\'envoi ajax : ' + data);
	}
})

Donc vous récupérez l'id_customer, vous l'envoyez à votre controleur en précisant l'action concernée (loadorders) et qu'on est en ajax.

Celui-ci va déclencher la fonction ajaxProcessLoadOrders() qui va récupérer les commandes, en extraire ce dont vous avez besoin (ID,Ref, etc...) et envoyer le tableau à un tpl (à créer dans /votremodule/views/templates/hook/order-list.tpl) qui va vous mettre le select en forme.

Le js va donc recevoir un js et il suffit de l'injecter à l'endroit voulu)

 

Dans le tpl vous avez juste à faire une boucle {foreach}

<select name="getRef">
{foreach $orders as $order}
  <option value="{$order.id}">{$order.reference}</option>
{/foreach}
</select>

 

Link to comment
Share on other sites

D'accord, mais dans mon cas je ne dois pas envoyer la variable à un tpl mais juste à mon adminController car je veux mettre les commandes dans un select :

array(
                    'type'    => 'select',
                    'label'   => $this->l('Order reference'),
                    'name'    => 'customer_orders',
                    'required' => true,
                    'options'  => array(
                        'query' => $options,
                        'id'    => 'id_order',
                        'name'  => 'name'
                    )
                ),

Est-ce que je dois aussi utiliser une fonction ajaxProcessLoadOrders ? Si oui est-ce que ajaxProcessLoadOrders doit retourner une valeur pour que je puisse l'utiliser en l'appellant et faire :

array(
                    'type'    => 'select',
                    'label'   => $this->l('Order reference'),
                    'name'    => 'customer_orders',
                    'required' => true,
                    'options'  => array(
                        'query' => $this->ajaxProcessLoadOrders(), // Récupération des commandes dans la fonction
                        'id'    => 'id_order',
                        'name'  => 'name'
                    )
                ),

 

Link to comment
Share on other sites

Non car le code que vous me montrez est un bout de helperform donc il faut le construire, faire un fetchTemplate et le renvoyer avec un die();

Les 2 solutions sont possibles.

Le helperform de base de votre controleur renvoie un contenu smarty à l'adminModule de Presta, dans votre cas vous voulez récupérer ce contenu pour l'injecter en js, ce n'est pas la même chose.

Je vous ai donné presque tout le code, pourquoi chercher plus compliqué ?

Link to comment
Share on other sites

ça c'est la partie qui m'intéresse dans mon renderForm() :

array(
                    'type' => 'customer_autocomplete',
                    'label' => $this->l('Customer'),
                    'name' => 'id_customer',
                    'lang' => false,
                    'col' => 5,
                ),
                array(
                    'type'    => 'select',
                    'label'   => $this->l('Order reference'),
                    'name'    => 'customer_orders',
                    'required' => true,
                    'options'  => array(
                        'query' => $options,
                        'id'    => 'id_order',
                        'name'  => 'name'
                    )
                )

$options doit contenir les commandes du client dynamiquement en fonction du champs customer_autocomplete du dessus (en se servant de la variable id_customer récupérée)

Link to comment
Share on other sites

il y a 8 minutes, GBPro a dit :

Parce que je ne comprends pas comment on peut modifier un template généré par le renderForm(). J'avoue ne pas comprendre...

En js, on injecte le contenu renvoyé par le controleur dans la page.

Comme Prestashop le fait pour les produits par exemple:

product.gif

Link to comment
Share on other sites

Ok donc il ne faut pas intégrer le champs select dans le renderForm() mais l'injection après en js ?

mais le template du formulaire admin du module rendu par renderForm() se situe où pour injecter ceci :

<select name="getRef">
{foreach $orders as $order}
  <option value="{$order.id}">{$order.reference}</option>
{/foreach}
</select>

 

Link to comment
Share on other sites

Ok je comprends mieux.

Par contre comment injecter ce tpl créé, juste après le champs de sélection du customer ? Faut-il l'appeler dans le tableau fields_form de l'admin controller ?

Comment lui dire précisément où aller ?

Link to comment
Share on other sites

Non, c'est votre js qui le fait au retour de l'ajax (seul le js peut modifier le DOM)

$.ajax({
	method: 'POST',
	url: ajax_link,
	cache: 'false',
	dataType: 'html',
	data: {
		ajax: true,
		action: 'loadorders',
		id_customer: id_customer_selected
	},
	success: function (data) {
		console.log(data);
		if(data){
			$(this).parent().append(data);
		}
	},
	error: function(data) {
		console.log('Erreur lors de l\'envoi ajax : ' + data);
	}
})

J'ai passé le retour en dataType html pour que ce soit plus simple pour vous

$(this) correspond à l'élément cliqué

Link to comment
Share on other sites

D'accord très bien. Merci

Donc si je veux par exemple modifier la valeur par défaut d'un autre input text en fonction de la référence de commande qui est sélectionnée parmi celles récupérées dans le select qui vient d'être injecté en js, je dois aussi le faire en js avec appel ajax c'est ça ?

Link to comment
Share on other sites

Ca dépend.

Si on veut "rafraichir" il faut regénérer le template et le renvoyer. Ce que fait Prestashop pour la page panier par exemple lorsque l'on modifie un des éléments du panier.

Soit on écrase tout, soit on met à jour que les éléments qui nous intéressent (grâce à leur ID)

Link to comment
Share on other sites

il faut faire un die() ensuite pour le revoyer au js.

Regardez comment est fait l'OrderOpcController par exemple:

                        case 'cartReload':
                            $this->_assignSummaryInformations();
                            if ($this->context->customer->id) {
                                $this->context->smarty->assign('address_list', $this->context->customer->getAddresses($this->context->language->id));
                            } else {
                                $this->context->smarty->assign('address_list', array());
                            }
                            $this->context->smarty->assign('opc', true);
                            $this->setTemplate(_PS_THEME_DIR_.'shopping-cart.tpl');
                            $this->display();
                            $this->ajaxDie();
                            break;

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...