3

I have a section for "tours" in my page.

The tours have 2 filters (select inputs). "destino" and "duracion" (location and duration)

So far I made one of the filter work with ajax, and update the "#result" id with the new tours once you select a "destino".

But i also want to update the "duracion" select with the new options (based on the destino selected).

Problem is, i have no idea how to execute two actions and have the response on two different places.

Html part: (here I have both actions, its only executing the last one)

<form class="filtros righter" action="**********/wp-admin/admin-ajax.php" method="POST" id="filtro">
<input type="hidden" name="action" value="filtertoursajax">
<input type="hidden" name="action" value="filterduracionajax">
<input type="hidden" name="filtrodestino" value="salar-de-uyuni">

        <div class="select-holder">
        <label class="">Categoría</label>   
            <select name="categoriafilter" id="categoriafilter">
                <option disabled="" selected="" value="0">&nbsp;</option>
                <option value="0">Todas las categorías</option>
                <option value="11">Clásicos</option>
                <option value="33">Elite</option>
            </select>
        </div>
        <div class="select-holder"> 
        <label>Duración del viaje</label>
            <select name="duracionfilter" id="resultselect">
                <option disabled="" selected="" value="0">&nbsp;</option>
                <option value="0">Todas las duraciones</option>
            </select>
        </div>
</form>

Js part:

<script>
jQuery(function myFunction(){
$('#filtro').change(function(){
    var filter = $('#filtro');
    $.ajax({
        url:filter.attr('action'),
        data:filter.serialize(), // form data
        type:filter.attr('method'), // POST
        beforeSend:function(xhr, data){
            filter.find('button').text('Processing...'); // changing the button label
        },
        success:function(data){
            filter.find('button').text('Apply filter'); // changing the button label back
            $('#response').html(data); // insert data
            console.log(data);
        },
        error: function(req, err){ console.log(err);
        }
    });
    return false;
});

});

PHP action 1:

add_action('wp_ajax_filtertoursajax', 'filtertoursajax');
add_action('wp_ajax_nopriv_filtertoursajax', 'filtertoursajax');


function filtertoursajax(){

    $args = array(
        'post_type' => 'tours',
        'orderby' => 'menu_order',
        'order' => 'ASC',
        'post_per_page' => -1,
    );

    if( isset($_POST['filtrodestino']) && $_POST['filtrodestino'] ) {

        // for taxonomies / categoria
            if( isset( $_POST['filtrodestino'] ) ) {
                $args['tax_query'][] = 
                    array(
                        'taxonomy' => 'destino',
                        'field' => 'slug',
                        'terms' => $_POST['filtrodestino']
                    
                );
            }           
    }


    if( isset($_POST['categoriafilter']) && $_POST['categoriafilter'] ) {

        // for taxonomies / categoria
                $args['tax_query'][] = 
                    array(
                        'taxonomy' => 'categoria',
                        'field' => 'id',
                        'terms' => $_POST['categoriafilter']
                    
                );
    }

 
    $query = new WP_Query( $args );
    if( $query->have_posts() ) :
        print_r($args);
        while( $query->have_posts() ): $query->the_post();

            $postid = $query->post->ID;

            $taxonomy = 'destino';  
            $terms = get_the_terms( get_the_ID(), $taxonomy );
                          
            if ( $terms && ! is_wp_error( $terms ) ) : 
             
                $term_links = array();
             
                foreach ( $terms as $term ) {
                    $term_links[] = '<a href="' . esc_attr( get_term_link( $term->slug, $taxonomy ) ) . '">' . __( $term->name ) . '</a>';
                }
                                     
                $all_terms = join( ', ', $term_links );
     
                $destinos = '<span class="terms-' . esc_attr( $term->slug ) . '">' . __( $all_terms ) . '</span>';
     
            endif;

            ?>
            <div class="box">
                <div class="box__image flexer">
                    <?php echo wp_get_attachment_image( get_field( "foto_portada", $postid ), array('276', '180'), "", array( "class" => "img-responsive" ) );  ?>
                </div>
                <div class="box__content pz-1">
                    <span class="placeholder mb-1"><?php echo $destinos; ?></span>
                    <h6 class="long-title mb-2"><?php echo $query->post->post_title; ?></h6>
                    <div class="icon-btn"><?php $path = get_template_directory_uri().'/images/plane-icon.svg'; echo file_get_contents($path); ?>Duración: <?php echo get_field( "duracion_texto", $postid ); ?></div>
                </div>
                <a href="<?php echo the_permalink(); ?>" class="text-btn pl-1">Ver ficha<?php $path = get_template_directory_uri().'/images/arrow-btn.svg'; echo file_get_contents($path); ?></a>
            </div>

        <?php endwhile;
        wp_reset_postdata();
    else:
        echo 'Sin resultados';
        print_r($args);
    endif;
 
    die();

}

PHP action 2:

add_action('wp_ajax_filterduracionajax', 'filterduracionajax'); // 
add_action('wp_ajax_nopriv_filterduracionajax', 'filterduracionajax');

function filterduracionajax(){

        if( $args = array(
                        'posts_per_page'    => -1,
                        'hide_empty' => 1,
                        'post_type'     => 'tours',
                        'meta_key'      => 'dias',
                        'orderby'           => 'meta_value',
                        'order'             => 'ASC',
                    ) ) :


        // create $args['tax_query'] array if one of the following fields is filled
    if( isset($_POST['filtrodestino']) && $_POST['filtrodestino'] ) {

        // for taxonomies / categoria
            if( isset( $_POST['filtrodestino'] ) ) {
                $args['tax_query'][] = 
                    array(
                        'taxonomy' => 'destino',
                        'field' => 'slug',
                        'terms' => $_POST['filtrodestino']
                    
                );
            }           
    }


// create $args['tax_query'] array if one of the following fields is filled
    if( isset($_POST['categoriafilter']) && $_POST['categoriafilter'] ) {

        // for taxonomies / categoria
                $args['tax_query'][] = 
                    array(
                        'taxonomy' => 'categoria',
                        'field' => 'id',
                        'terms' => $_POST['categoriafilter']
                    
                );
    }


        // query
        $the_query = new WP_Query( $args );
        if( $the_query->have_posts() ): ?>

        <div class="select-holder"> 
        <label>Duración del viaje</label>
        <select name="duracionfilter" id="resultselect">
        <option disabled="" selected="" value="0">&nbsp;</option>
        <option value="0" >Todas las duraciones</option>
            
            <?php $unique_dias = array();

            while( $the_query->have_posts() ) : $the_query->the_post(); ?>
                <?php $dias = get_field('dias');

                if( ! in_array( $dias, $unique_dias ) ) :
                            $unique_dias[] = $dias; ?>
                <?php endif;
            endwhile;
            natsort($unique_dias);
            foreach ( $unique_dias as $duraciones ) :
                    echo '<option value="'.$duraciones.'">'.$duraciones.'</option>';
            endforeach;

            ?>

        </select></div>
        <?php endif;

     endif;

     die();

}

Im very new with Ajax, this code is made by pieces of tutorials i found. The code is mostly made following this tutorial: https://rudrastyh.com/wordpress/ajax-post-filters.html I just need both php actions to execute on "form" change and update the "tours" on #response div and also update the select input with #resultselect id.

Thanks!


Thanks to @lewis4you I'm able to get the data on the 2 divs at the same time. But i fail to understand how to execute both actions at the same time, but with different actions from functions.php

This

add_action('wp_ajax_filterduracionajax', 'filterduracionajax'); // 
add_action('wp_ajax_nopriv_filterduracionajax', 'filterduracionajax');

has to return data to #resultselect

and

add_action('wp_ajax_filtertoursajax', 'filtertoursajax'); 
add_action('wp_ajax_nopriv_filtertoursajax', 'filtertoursajax');

has to return data to #response div

My main problem is that i dont know how to select the action i want to execute in

$.ajax({
          url:filter.attr('action'),
          data:filter.serialize(), // form data
          type:filter.attr('method'), // POST
1
  • Also another solution would be to have an endpoint for supplementary data which returns the data for both in one call Commented Jun 30, 2020 at 7:47

2 Answers 2

2

I didn't read the question fully but I think you want something like this:

$('#filtro').change(function() {
    var filter = $('#filtro');
    ajax1(filter);
    ajax2(filter);
});


function ajax1(filter) {
 $.ajax({
    url:filter.attr('action'),
    data:filter.serialize(), // form data
    // ... further code
}

function ajax2(filter) {
 $.ajax({
    url:filter.attr('action'),
    data:filter.serialize(), // form data
    // ... further code
}

The scenario where you send the data to the same controller from one $.ajax call:

$('#filtro').change(function() {
    var filter = $('#filtro');
    ajax1(filter);
});

in controller you have to store the data into array with keys so you can access it later in ajax success() function

public function someFunction($dataFromAjax) {

    // do something with $dataFromAjax

    $dataForDivs = [
        'div1' => 'some data',
        'div2' => 'some data2'
    ];

    return $dataForDivs;
}

then in your $ajax in success:function(data) you can access that data with

success:function(data) {
    let div1Data = data.responseJSON.div1;
    let div2Data = data.responseJSON.div2;
    filter.find('button').text(div1Data); // changing the button label back
    $('#response').html(div2Data); // insert data
    console.log(div1Data, div2Data);
},
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for your time. This is one step closer. With this code i can get the response data to both divs at the same time. But i don't know how to execute the 2 functions/actions. I think my main problem is that i don't understand how to set a specific action to an ajax call. in $.ajax I need two actions to execute and return the data on two divs. add_action('wp_ajax_filtertoursajax', 'filtertoursajax'); // return data to #response div add_action('wp_ajax_filterduracionajax', 'filterduracionajax'); // return data to #resultselect
1

Have you thought of using JS's Fetch API instead of jQuery's Ajax? Fetch returns a promise then it can execute a chain of .then() blocks where you can put another fetch() to your PHP url.

See an example here:

using a fetch inside another fetch in javascript

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.