Twitter's typeahead-bloodhound: What is the equivalent of “%QUERY” when using ajax.data and POST?

﹥>﹥吖頭↗ 提交于 2019-11-27 08:17:31

问题


If one uses Bloodhound with GET:

// Typeahead
personsBloodhound = new Bloodhound({
    datumTokenizer: function (person) { return person.name; },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: {
        url: '/ajax/Persons/List?nameContains=%QUERY',
        ajax: {
            beforeSend: function(xhr) {
                $(".searching-person").show();
            },
            data: {
                "pageSize": 4,
                "otherParam1": "blah",
                "otherParam2": "bleh",
            }
        },
        filter: function (response) {
            $(".searching-person").hide();
            return response.persons;
        }
    }
});

One simply uses %QUERY in the URL.

Now....
If one uses Bloodhound with POST, what should I use instead of %QUERY?

// Typeahead
personsBloodhound = new Bloodhound({
    datumTokenizer: function (person) { return person.name; },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: {
        url: '/ajax/Persons/List',
        ajax: {
            type: "POST",
            beforeSend: function(xhr) {
                $(".searching-person").show();
            },
            data: {
                "nameContains": ....WHAT GOES HERE?????......
                "pageSize": 4,
                "otherParam1": "blah",
                "otherParam2": "bleh",
            }
        },
        filter: function (response) {
            $(".searching-person").hide();
            return response.persons;
        }
    }
});

If it was not clear, the question is:
What is the equivalent of %QUERY when using POST within Bloodhound's remote?

The documentation isn't clear about this, (proof): https://github.com/twitter/typeahead.js/blob/master/doc/bloodhound.md#remote

Also tried using:

 "nameContains": $("#my-input-that-uses-typeahead").val(),

But didn't work.


回答1:


You have to alter the URL somehow, otherwise the bloodhound wont send an other request (see https://stackoverflow.com/a/24025789/2175370) and livesearch/typeahead wont work.

So ("#my-input-that-uses-typeahead").val() works just fine in combination with a dynamic URL (e.g.http://127.0.0.1:1234/REST_API/_search?useless=%QUERY) and a beforeSend-function in the ajax setttings.

I gonna file an issue about this behaviour. Using the bloodhound for POST-requests ist VERY awkward and takes away the simplicity intended with typeahead.js.

EDIT:

Also make sure you set the new value for the data in beforeSend and set settings.hasContent = true. Otherwise the initial data will be used.

Example on how it's done: https://github.com/twitter/typeahead.js/issues/542#issuecomment-29995960.




回答2:


Right, after further looking at bloodhound the wildcard is just what to replace not the value.

It doesn't store the query string anywhere. On queryChanged fires and filters remote response. Looks like you'll have to get the query yourself.

"nameContains": $('input#search').val()



回答3:


Equivalent of %QUERY when using POST within Bloodhound's remote is query.

Here is a simple example (with detailed explanation) where you can use it for both GET and POST. As you can see I have declared a variable isExtendUrl. If this is set to true then the query (what you type) will be added to the end of the url (you have to give the myurl somehow).

The next variable is isRequestMethod. If this is set to POST, you can use bloodhound for POST calls else you can use it for GET calls. As you can see prepare function has two parameters query and setting. query is the one what you type. If you just want the POST call without GET move prepare key value pair inside remote object.

So, if you have to use JSON body as {gender: 'MALE', name: 'what is typed'} for your POST call. You can have an initial query object with all your key value pairs eg: initialQuery = {gender: 'MALE'}, and the key searchKey which should be added to initialQuery when searching, could be added on prepare like initialQuery[searchKey] = query.

Finally, if the response object of your POST call is an object and you have to extract a specific key value use filter. Eg: Say your response object is

{
  status: 'some status', 
  content: [{array}, {of}, {objects}, ...], 
  someKey: someValue
} 

and you have to get content, then return data.content. Here is a full example

let isExtendUrl = true; //to add query at the end of the url, usually used with GET
let isRequestMethod = 'POST';
let initialQuery = {gender: 'MALE'};
let searchKey = 'name';

let bloodhound = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.whitespace,
    queryTokenizer: Bloodhound.tokenizers.whitespace,

    remote: {
        url: isExtendUrl ? myurl + '%QUERY' : myurl,
        wildcard: '%QUERY',
        filter: function (data) {
            return $.map(data.content, function (obj) {
                return obj;
            });
        }
    }
});

if (isRequestMethod == 'POST') {
    let prepare = function (query, settings) {
        initialQuery[searchKey] = query;
        settings.type = "POST";
        settings.contentType = "application/json; charset=UTF-8";
        settings.data = JSON.stringify(initialQuery);

        return settings;
    }
    bloodhound.remote.prepare = prepare;
}


来源:https://stackoverflow.com/questions/24108519/twitters-typeahead-bloodhound-what-is-the-equivalent-of-query-when-using-aj

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!