Filtrare un secondo menu a discesa quando viene selezionato un valore nel primo
Ho una tabella con due menu a discesa. Il primo è per la marca, che è un custom post type di WordPress. Il secondo è per gli aromi, anch'esso un custom post type. La marca è il genitore degli aromi. Quando seleziono una marca, ho bisogno di aggiornare il secondo menu a discesa con gli aromi di quella marca (i figli).
Ho creato degli shortcode per le mie liste e vengono popolati correttamente. Ma non so come filtrare il secondo menu a discesa quando il primo cambia.
Ecco la mia tabella:
<table id="fla_inf" width="100%">
<tbody>
<tr>
<th class="tab_header" colspan="6">Aromi e Additivi</th>
</tr>
<tr>
<th class="tab_header_nam">Marca dell'Aroma</th>
<th class="tab_header_nam">Nome dell'Aroma</th>
<th class="tab_header_nam">Tipo di contagocce</th>
<th class="tab_header_nam">Unità di quantità</th>
<th class="tab_header_nam">Quantità</th>
<th class="tab_header_nam">Aggiungi/Rimuovi riga</th>
</tr>
<tr class="flavors">
<td>[brand_list]</td>
<td>[flavor_list]</td>
<td><select id="dropper0" class="dropper">
<option selected="selected" value="type1">tipo 1</option>
<option value="type2">tipo 2-3</option>
</select></td>
<td><select id="qtyunit0" class="qtyunit">
<option value="ml">ml</option>
<option value="drops">gocce</option>
<option selected="selected" value="perc">%</option>
</select></td>
<td><input id="quantity0" class="quantity" type="number" /></td>
<td><input class="addline" src="http://spitilab.com/wp-content/uploads/2015/01/add.png" type="image" /><input class="remline" src="http://spitilab.com/wp-content/uploads/2015/01/delete.png" type="image" /></td>
</tr>
</tbody>
</table>
Ecco i miei shortcode:
function GetBrandList() {
$brands = wp_dropdown_pages(array('id'=>'marque0','post_type' => 'marque-type','echo'=>0));
return $brands;
}
function GetFlavorList() {
$flavors = wp_dropdown_pages(array('id'=>'arome0','post_type'=>'aromes-type','echo'=>0));
return $flavors;
}
add_shortcode('brand_list', 'GetBrandList');
add_shortcode('flavor_list', 'GetFlavorList');
Ecco il mio aggiornamento:
Ho aggiunto quanto segue al mio functions.php
add_action( 'wp_ajax_brand_children', 'GetBrandChildren');
add_action( 'wp_ajax_nopriv_brand_children', 'GetBrandChildren');
function GetBrandChildren($parent_id,$id) {
$children = wp_dropdown_pages(array('id'=>'arome$id','post_type'=>'aromes-type','child_of'=>$parent_id,'echo'=>0));
return $children;
}
e qui il mio jquery:
//Quando si seleziona una marca, aggiorna la lista degli aromi
$(document).on('change', "select[id^='marque']", function() {
var $brandid = $(this).val();
var $brand_dd_id = $(this).attr('id');
var $flav_dd_id = $brand_dd_id.substr($brand_dd_id.length-1);
$("#arome"+$flav_dd_id).empty();
//Effettua una richiesta AJAX, usando il valore selezionato come GET
$.ajax({data: '{"parent_id":"' + $brandid + '","id":"'+ $flav_dd_id +'","action":"brand_children"}',
success: function(output) {
alert(output);
$("#arome"+$flav_dd_id).html(output);
}
});
});
Tuttavia, il mio menu a discesa degli aromi rimane vuoto. Nell'output mostrato nell'alert, sembra che venga restituita l'intera pagina html.
AGGIORNAMENTO:
add_action( 'wp_ajax_brand_children', 'GetBrandChildren');
add_action( 'wp_ajax_nopriv_brand_children', 'GetBrandChildren');
function GetBrandChildren() {
$parent_id = $_POST['brandid'];
$id = $_POST['flav_dd_id'];
echo wp_dropdown_pages(array("id"=>"arome$id",'post_type'=>'aromes-type','child_of'=>$parent_id,'echo'=>0));
//ob_clean();
//echo "working";
wp_die();
}
// servono queste due righe per poter localizzare admin-ajax.php dentro jquery
wp_enqueue_script( 'my-ajax-request', get_template_directory_uri() . '/js/ajax.js', array( 'jquery' ) );
wp_localize_script( 'my-ajax-request', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
il JQuery:
//Quando si seleziona una marca, aggiorna la lista degli aromi
$(document).on('change', "select[id^='marque']", function() {
var $brandid = $(this).val();
var $brand_dd_id = $(this).attr('id');
var $flav_dd_id = $brand_dd_id.substr($brand_dd_id.length-1);
$("#arome"+$flav_dd_id).empty();
//Effettua una richiesta AJAX, usando il valore selezionato come GET
//var ajax_url = admin_url('admin-ajax.php');
$.ajax({
url: MyAjax.ajaxurl,
data: {
'parent_id': $brandid,
'id': $flav_dd_id,
'action': 'brand_children'
},
success: function(output) {
console.log(output);
$("#arome"+$flav_dd_id).html(output);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status + " "+ thrownError);
}});
});
ora il mio secondo menu a discesa viene aggiornato.

Dovrai utilizzare Ajax per ottenere che il secondo menu a discesa si carichi dopo che il primo è stato selezionato. Non sono sicuro di un paio di cose che hai lì, quindi mi limiterò a scriverti il codice, potresti dover modificare qualcosa qui o là, cercherò di completarlo nel modo più accurato possibile. La prima cosa da fare è impostare un'azione Ajax. Idealmente, questo dovrebbe essere configurato all'interno di un plugin. La funzione is_admin() viene utilizzata perché quando la richiesta Ajax viene inviata dalla pagina con il tuo menu a discesa, verrà eseguita nell'area di amministrazione. Se ti sembra che stiamo lavorando al contrario, è solo una questione di causa-effetto. Cosa viene prima, la richiesta o il gestore... il gestore ovviamente, ed è per questo che inizio da qui.
<?php
if ( is_admin() ) {
// Aggiungiamo 2 azioni, la prima per gli utenti loggati, la seconda per gli ospiti.
add_action( 'wp_ajax_dynamic_dropdown', 'dynamic_dropdown_func' );
add_action( 'wp_ajax_nopriv_dynamic_dropdown', 'dynamic_dropdown_func' );
}
// Questa è la funzione che gestirà la tua richiesta/risposta Ajax
function dynamic_dropdown_func () {
global $wpdb;
if (isset($_POST['value'])) {
$selected_option = $_POST['value'];
// Questo sarà il tuo secondo menu a discesa, verrà restituito in una richiesta Ajax
$args = array(
'show_option_none' => __( 'Scegline un altro' ),
'class' => 'dropper',
'id' => 'dropper0',
'orderby' => 'ID',
'order' => 'ASC',
'hide_empty' => 0,
'hierarchical' => 1,
'depth' => 1,
// Questo è ciò che ci darà i figli dell'opzione selezionata inizialmente
'child_of' => (int)$selected_option,
'echo' => 0,
// Assicurati di sostituire questa costante con la tua tassonomia
'taxonomy' => MY_CUSTOM_TAX,
);
$my_second_dropdown = wp_dropdown_categories( $args );
// Se vuoi fare preg_replace o str_replace, fallo qui prima di eseguire ob_clean() sotto
}
// ob_clean serve per prevenire errori, echo o qualsiasi cosa che sia stata outputtata fino a questo punto nell'istanza Ajax di WP che potrebbe rovinare il tuo return.
ob_clean();
return $my_second_dropdown;
wp_die();
}
Ok, ora passiamo alla parte front-end del codice. Questa è la parte che vedrà l'utente. Quando attiverà la richiesta Ajax, al ricevimento della risposta il secondo menu a discesa dovrebbe caricarsi. Normalmente, dovresti localizzare un file JavaScript con la variabile per ajax_url e qualsiasi altro valore PHP che dobbiamo usare nel nostro JS per inviare richieste Ajax a WP. Faremo un piccolo trucco e stamperemo direttamente il nostro script nella pagina, ottenendo lo stesso risultato. Assicurati solo di stampare questo script alla fine del body, idealmente, altrimenti dovrai aggiungere una funzione document ready, comunque non farebbe male.
function my_frontend_javascript () {
$ajax_url = admin_url( 'admin-ajax.php' );
$javascript = "
<script>
var ajaxUrl = {$ajax_url},
// Ora prendiamo i nostri menu a discesa
dropdownArome = jQuery('#arome0'),
dropdownDropper = jQuery('#dropper0');
if (dropdownArome.length && dropdownDropper.length) {
// Bene, i nostri elementi esistono
dropdownArome.on('change', function (e) {
var value = e.target.selectedOptions[0].value,
success,
data;
if (!!value) {
// Bene, inviamo quel valore al nostro script Ajax, nota che l'azione è la stessa dell'hook Ajax usato prima
data = {
'my_value' : value,
'action' : 'dynamic_dropdown'
};
success = function ( response ) {
// Questa risposta conterrà i nostri <option>
dropdownDropper.html( response );
};
jQuery.post( ajaxUrl, data, success );
}
});
}
</script>";
return $javascript;
}
/** Qui è dove costruiamo il nostro sito/form/menu a discesa */
$args = array(
'show_option_none' => __( 'Scegline uno' ),
'class' => 'arome',
'id' => 'arome0"',
'orderby' => 'ID',
'order' => 'ASC',
'hide_empty' => 0,
'hierarchical' => 1,
'depth' => 1,
'echo' => 0,
// Assicurati di sostituire questa costante
'taxonomy' => MY_CUSTOM_TAX,
);
$my_first_dropdown = wp_dropdown_categories( $args );
// Bene, ora stampiamo i 2 menu a discesa, poi lo JavaScript dalla funzione scritta sopra
echo $my_first_dropdown;
echo '<br /><div id="dropper0-container"></div><br />';
echo my_frontend_javascript();
/** Questo dovrebbe essere tutto! Come ho detto, dovrai modificare alcune opzioni per adattarle al tuo sito e alla tua implementazione. */
Quindi, questo è il modo in cui potresti fare ciò che stai cercando di fare, in quello che immagino sia uno dei modi più semplici. Dico più semplice perché in realtà non abbiamo fatto alcuna validazione, nonce, abbiamo praticamente presupposto che tutto sia andato bene. Suggerirei di approfondire l'uso di Ajax in WP, anche se ne sai già qualcosa, non fa mai male saperne di più. Spero che questo codice funzioni bene per te con qualche modifica.
http://codex.wordpress.org/AJAX_in_Plugins
http://www.smashingmagazine.com/2011/10/18/how-to-use-ajax-in-wordpress/

Ciao oneThingSimple,
Non mi aspettavo una risposta così completa, grazie mille per aver dedicato del tempo a spiegarmi. Sono molto nuovo con ajax, questa è in realtà la prima volta che ho bisogno di usarlo. Proverò ad adattare la tua risposta a ciò che mi serve, è davvero di grande aiuto.
Grazie ancora.
Cyrille

@user3515709 Va bene, nessun problema. Ajax può essere un po' complicato all'inizio. Sarebbe bene che tu familiarizzassi con il funzionamento dell'oggetto jQuery Ajax. È l'oggetto che usiamo principalmente in WP per inviare richieste asincrone. Come sviluppatore direi che jQuery vale il suo peso solo per l'oggetto Ajax. Se hai bisogno di aiuto, puoi contattarmi, cercherò di rendere la cosa meno dolorosa per te, perché sarà complesso finché non avrai capito l'intero processo, poi diventerà come qualsiasi altra cosa. Quindi se ti senti frustrato fammelo sapere.

ho aggiornato il mio codice, ho un problema con l'output. Probabilmente qualcosa che ho sbagliato.

@user3515709 Finirò con il lavoro tra 4 ore. Se vuoi che dia un'occhiata al codice, posso farlo con te. Proverò ad aiutarti a farlo funzionare. Sia nella chat room qui su stackexchange che via email mike@stayshine.com e possiamo discuterne fuori dal forum. Buona fortuna.

Ancora nessun successo con questo. Penso ci sia un problema con il mio codice ma anche con la mia funzione wp_dropdown_pages perché ho creato uno shortcode per visualizzare i figli di un genitore specifico e il dropdown mostra: "Pagina principale (nessun genitore)"

Con la tua funzione function GetBrandChildren($parent_id,$id) in realtà non stai ottenendo i dati inviati nella richiesta Ajax come argomenti. Devi ottenere quei valori dall'array $_POST. Non c'è bisogno di tentare di convertire manualmente il tuo oggetto dati in stringa. Usa semplicemente un normale oggetto JavaScript. jQuery si occuperà della serializzazione degli argomenti. Inoltre, ricorda di usare echo per Children, non return. Dopo averlo stampato con echo, usa wp_die() in modo che la pagina sia completa e venga inviata, senza che venga aggiunto altro contenuto.

grazie per il tuo input, ho modificato il codice secondo le tue raccomandazioni. C'è un modo per verificare se l'output restituito è corretto? Quando mostro l'output in un alert, sembra che venga restituita l'intera pagina

1 Non hai l'url nel tuo oggetto ajax quindi non invierà i dati da nessuna parte. Per prima cosa, dovresti provare a usare console.log(msg) invece di alert(msg), non solo per tua tranquillità, ma anche perché il logging nella console ti dà un accesso migliore a tutto ciò che devi ispezionare, l'alert blocca ed è solo testo. Un modo semplice per assicurarti che i gestori delle azioni ajax vengano chiamati dopo è semplicemente scrivere all'interno della funzione handler ob_clean();echo "I WORK!";wp_die();
Questo cancellerà qualsiasi output di altre funzioni e restituirà solo "I WORK" al successo di $.ajax se l'intera richiesta è configurata correttamente.

funziona, ora il dropdown funziona, il problema rimanente è il wp_dropdown_pages che non viene filtrato con l'id del genitore.

@user3515709 Dovresti convertire $parent_id in un Integer. Quindi sarebbe 'child_of' => (int)$parent_id,
Preferisco mantenere i miei $args in una variabile piuttosto che direttamente nella chiamata alla funzione in modo che durante il debug posso fare var_dump(), print_r(), var_export(), ora che hai l'ajax funzionante, questi torneranno nella risposta così puoi effettuare il debug. Sto uscendo per stasera. Se riesci a farlo funzionare, per favore segnala la mia risposta. Se hai bisogno di ulteriore aiuto, puoi inviarmi una email all'indirizzo che ho lasciato nei commenti o possiamo spostarci in una chat domani. Buona fortuna
