bp-better-directories icon indicating copy to clipboard operation
bp-better-directories copied to clipboard

1.0.x bp-better-diretories

Open pierre-dickinson opened this issue 8 years ago • 15 comments

Hi Boone, I'm wondering if i still can use your plugin, but i have been trying to simply update the Members Loop using Ajax on a "click" event on a link in the Members directory but i can't figure out what is wrong? the loop is not refreshed in ajax on click. please help ! here is my code :

function special_bp_dtheme_ajax_querystring( $query_string, $object ) {

    /* for testing purpose : Now pass the querystring to override default values. */
    $list_of_members = '1,2,3';
    $query_string .= '&type=active&action=active&include='. $list_of_members .'&page=1';
    return $query_string;
}
// this doesnt work
//add_filter( 'bp_dtheme_ajax_querystring', 'special_bp_dtheme_ajax_querystring', 11, 2 );

 // this work (on page load not in ajax)
//add_filter( 'bp_ajax_querystring', 'special_bp_dtheme_ajax_querystring', 11, 2 );

/*
* source: https://buddypress.org/support/topic/simply-trying-to-filter-the-bp_ajax_querystring-via-ajax/
*  this action is located in _inc/ajax.php : 
add_action( 'wp_ajax_members_filter', 'bp_dtheme_object_filter' );
*/
function my_ajax() {
    //add_action( 'wp_ajax_members_filter', 'special_bp_dtheme_ajax_querystring' );
    //add_filter( 'bp_ajax_querystring', 'special_bp_dtheme_ajax_querystring', 11, 2 );
    add_filter( 'bp_dtheme_ajax_querystring', 'special_bp_dtheme_ajax_querystring', 11, 2 );
}

and here is my js :

$('#custom-members-search-trigger').on('click', function (e) {
                    e.preventDefault;
                    console.log('button clicked!');

                    $.post(
                        ajaxurl, 
                        {
                            'action': 'my_ajax',
                            'data':   'test'
                        }, 
                        function(response){
                            alert('The server responded: ' + response);
                        }
                    );

                });

What's wrong? Please help me with this, it must be "simple" ;-)

pierre-dickinson avatar Oct 15 '16 22:10 pierre-dickinson

@mecanographik

function(response){
    alert('The server responded: ' + response);
}

I'm assuming that the alert is showing nothing. If you are sending an AJAX request with action: 'my_ajax', then you need a PHP callback hooked to 'wp_ajax_my_ajax'. https://www.smashingmagazine.com/2011/10/how-to-use-ajax-in-wordpress/ is a good tutorial.

In order to refresh the member directory using AJAX, your PHP callback needs to load the templates. BP does it with a generic template loader: https://buddypress.trac.wordpress.org/browser/tags/2.6.1/src/bp-templates/bp-legacy/buddypress-functions.php#L748

Your filter on bp_dtheme_ajax_querystring will only do anything if you're actually loading the members directory in your AJAX callback. Once you get that part working, you'll be in a better position to debug whether your filter is working properly. A hint: you're probably going to need to have some sort of if statement to make sure you're not always filtering the querysting, but are only doing it on my_ajax requests.

boonebgorges avatar Oct 16 '16 15:10 boonebgorges

Hi @boonebgorges thanks for your answer. I did have already put the 'wp_ajax_my_ajax' part, but i'm sorry i've forgotten to paste it with the previous comment ;-) I understand the ajax template loader concept, but do i need to create some extra templates and load them in ajax depending on the filter i need to apply in ajax? How do i call the following action ? like this ?

add_action( 'wp_ajax_members_filter', 'bp_legacy_theme_object_template_loader');

Where do i pass the $query_string parameters to rebuild the query with some meta keys / meta values for example?

Do i need to use the bp_dtheme_ajax_querystring function define in ajax.php ?

Thanks for your answer

pierre-dickinson avatar Oct 17 '16 07:10 pierre-dickinson

Hi @boonebgorges

I’m working with @mecanographik on this project.

I follow your advices and here is what i can do :

I load the template BuddyPress in my php callback and i can update the member directory using AJAX.

Is it the best way to load the template and update the loop ?

// check for routing via AJAX
if (defined('DOING_AJAX') AND DOING_AJAX) {
    add_filter('bp_dtheme_ajax_querystring', 'my_ajax_test', 11, 2);
}
function my_bp_loop_querystring( $query_string, $object ) {
    if ( ! empty( $query_string ) ) {
        $query_string .= '&';
    }

    $list_of_members = '1, 2, 5, 33, 43';

    $query_string .= '&type=active&action=active&include=' . $list_of_members . '&page=1';

    return $query_string;
}
function my_ajax_test($query_string, $object) {

    add_action('bp_legacy_theme_ajax_querystring', 'my_bp_loop_querystring', 20, 2);

    bp_get_template_part('members/members-loop');

    wp_die();
}

my_ajax_test() returns an HTML string. I update the DOM with this string.

$('#buddypress #members-directory-form').html(data);

Thanks for your help !

SebastienGicquel avatar Oct 17 '16 13:10 SebastienGicquel

Hi @vinylroads - Yes, something like this seems correct. The DOING_AJAX check for filtering bp_dtheme_ajax_querystring is probably going to be too general, though - it'll add the include parameter for any directory that is powered by AJAX. It looks to me like you can just remove this chunk and rely on the add_action() call inside of my_ajax_test().

boonebgorges avatar Oct 17 '16 14:10 boonebgorges

Hi @boonebgorges

Glad to see it seems ok for you.

I thought of an improvement :

Previously, i have tested and call JS function members_filter() in the JS AJAX function :

            type: "POST",
            url: ajaxurl,
            data: {
                action: 'members_filter',
                object: 'members',
                cookie: encodeURIComponent(document.cookie),
                search_terms: 'pierre'

            }

This function is really simple to use : It refreshes the member loop without the need to update the DOM in the success: function

Unfortunately, we can only send in $_POST : page, exclude_just_posted, search_terms.

I need to filter users with meta_value.

So, in bp_dtheme_ajax_querystring() (in buddypress/bp-themes/bp-default/_inc/ajax.php), i see after all the datas are received with POST :

// Now pass the querystring to override default values.

So, i was wondering if it would be possible to modify the querystring here in order to pass meta_value (or anything else possible with querystring).

SebastienGicquel avatar Oct 17 '16 15:10 SebastienGicquel

Unfortunately, we can only send in $_POST : page, exclude_just_posted, search_terms.

I don't understand why you have this restriction. exclude_just_posted is related to activity, not to members. And if you're writing your own JS to make the AJAX call, just add things like meta_value and meta_key to your data array.

So, i was wondering if it would be possible to modify the querystring here in order to pass meta_value (or anything else possible with querystring).

I would think that something like the following would work:

function my_bp_loop_querystring( $query_string, $object ) {
    if ( ! empty( $query_string ) ) {
        $query_string .= '&';
    }

    $query_string .= '&type=active&action=active&page=1';

    if ( isset( $_POST['meta_key'] ) && isset( $_POST['meta_value'] ) ) {
        $meta_key = wp_unslash( $_POST['meta_key'] );
        $meta_value = wp_unslash( $_POST['meta_value'] );
        $query_string .= '&meta_key=' . urlencode( $meta_key ) . '&meta_value=' . urlencode( $meta_value );
    }

    return $query_string;
}

boonebgorges avatar Oct 17 '16 15:10 boonebgorges

Thanks for the code. I think i know how to filter with meta_value because i already do it without ajax (with simple page refresh).

I was just wondering if it was possible to use a built in function like members_filter() but nevermind. I will use my own JS in order to add custom filter to the Members and Groups. I’ll show you the result when the site will be online.

Regards,

Sébastien

SebastienGicquel avatar Oct 17 '16 20:10 SebastienGicquel

Thanks! Looking forward to seeing how it works out.

On 10/17/2016 03:07 PM, vinylroads wrote:

Thanks for the code. I think i know how to filter with meta_value because i already do it without ajax (with simple page refresh).

I was just wondering if it was possible to use a built in function like |members_filter()| but nevermind. I will use my own JS in order to add custom filter to the Members and Groups. I’ll show you the result when the site will be online.

Regards,

Sébastien

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/boonebgorges/bp-better-directories/pull/7#issuecomment-254318202, or mute the thread https://github.com/notifications/unsubscribe-auth/AAPDY9BSo1pGsCN_JvrFOBZCx46KcjiAks5q09WSgaJpZM4KX1NR.

boonebgorges avatar Oct 18 '16 02:10 boonebgorges

Thanks so much @boonebgorges @imath @vinylroads , This snippet looks promising. The members_filter action (in ajax.php) seemed to be the best way but it looks like we can't manage Meta Key filtering with this core action. So this custom function will help us to break through the Buddypress Ajax template loading and filtering system. We won't forget to share the final Plugin or Public Gist with the whole working snippet and the demo URL ;-)

pierre-dickinson avatar Oct 18 '16 07:10 pierre-dickinson

Hi @boonebgorges,

Could you give me an advice on this ?

I would like to filter the members loop with multiple meta_key and meta_value (because i have multiple selects in my form).

for example :

meta_key=city
meta_value=chicago

meta_key=job
meta_value=developer

Here is how i build my query. I’ve tested it with a simple native WordPress $user_query = new WP_User_Query($args); and it was working. So i think my array is correct.

So, how can i pass this array to the buddypress querystring.

Here is the code :

    $query_string .= '&type=active&action=active&page=1';

    $query_array = array('relation' => 'AND');

    // querystring as an array
    $defaults = array(
        'type' => 'active',
        'action' => 'active',
        'scope' => 'all',
        'page' => 1,
        'user_id' => 0,
        'search_terms' => '',
        'exclude' => false,
    );

    $args = array(
        'meta_query' => $query_array,
    );

When i retrieve the datas sent by POST, i use array_push in order to build the array :

    if (!empty($_POST['ville'])) {
        $meta_value_ville = $_POST['ville'];
        array_push($query_array, array('meta_key' => 'ville', 'meta_value' => $meta_value_ville));
    }

Then, i use bp_parse_args

$query_string = bp_parse_args($args, $defaults);

Here is a print of the final array with multiple meta_key and meta_value :

Array

(
    [type] => active
    [action] => active
    [scope] => all
    [page] => 1
    [user_id] => 0
    [search_terms] => 
    [exclude] => 
    [meta_query] => Array
        (
            [relation] => AND
            [0] => Array
                (
                    [meta_key] => ville
                    [meta_value] => Nantes
                )

            [1] => Array
                (
                    [meta_key] => user_metiers
                    [meta_value] => 297
                )

        )

)

This array seems correct. But the query string is not filtered.

If i add a 'search_terms' in thedefault array` :

'search_terms' => 'pierre',

I can get all the members containing 'pierre' so i think that this is correct :

$query_string = bp_parse_args($args, $defaults);

The query string is filtered.

Do you think it’s possible to have multiple meta_key / meta_value with the buddyPress querystring ? (i know it’s possible with WordPress, already done that).

Thank you for your help, regards !

SebastienGicquel avatar Oct 18 '16 15:10 SebastienGicquel

Hi,

Let me know when you have time if it’s possible to use nested arrays (complex queries / Multiple custom user fields handling) like as we can use with WordPress. Something like https://codex.wordpress.org/Class_Reference/WP_Meta_Query

But otherwise, i found an easy solution which is ok. I would prefer to use nested array because i guess it’s cleaner.

So, my solution : I get all the user ids :

$user_query = new WP_User_Query($args);

I build a coma separated list :

foreach ($user_query->results as $user) {
        $users_list .= $prefix  . $user->ID;
        $prefix = ', ';
    }

(here, i could improve my code without a foreach and use something like $users_list = implode(', ', $user_query); but i need to rebuild user_query It's on my toDoList ;-)

Then, the querystring :

$query_string .= '&include='.$users_list;

It works, i can filter members loop with different meta_key / meta_value ... yeah !

SebastienGicquel avatar Oct 18 '16 20:10 SebastienGicquel

Hi @vinylroads - Thanks for the updates!

It might be possible to build a complex meta_query parameter as part of the querystring. It'd have to look like this:

&meta_query[first_clause][key]=foo&meta_query[first_clause][value]=bar...

This would probably work, but it'd be quite clumsy. Your solution is probably just as good.

In the future, it'd be nice if there were an easier way to intervene in bp_ajax_querystring() without having to build an actual querystring. This can currently be done at the level of the individual queries, using filters like bp_pre_has_members_parse_args, but there's no global way to do it.

boonebgorges avatar Oct 19 '16 01:10 boonebgorges

Hi @boonebgorges @imath - How are you? I want to thank you again for your precious help on this project, you can check it out the buddypress acf ajax search demo we have built here : https://v2.laplateforme.net/individus/

click on the yellow button "filtres" ... ;-)

Regards,

pierre-dickinson avatar Apr 05 '17 12:04 pierre-dickinson

La page n'arrive pas à charger :(

On 04/05/2017 07:01 AM, Pierre Dickinson wrote:

Hi @boonebgorges https://github.com/boonebgorges - How are you? I want to thank you again for your precious help on this project, you can check it out the buddypress acf ajax search demo we have built here : https://v2.laplateforme.net/individus/

click on the yellow button "filtres" ... ;-)

Regards,

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/boonebgorges/bp-better-directories/pull/7#issuecomment-291839764, or mute the thread https://github.com/notifications/unsubscribe-auth/AAPDY-MZ1Sn2GbfDvStc9xH4nehmtgu7ks5rs4KFgaJpZM4KX1NR.

boonebgorges avatar Apr 05 '17 14:04 boonebgorges

Hello, could you try again ? We can can see the page, not sur why you can't...

SebastienGicquel avatar Apr 05 '17 15:04 SebastienGicquel