Как выглядит автозаполнение запроса / ответа сервера?

Кажется, это черная дыра: после часа поиска на веб-сайте jQuery UI, переполнения стека и поиска в Google мне еще предстоит найти основную информацию о том, как написать серверную часть автозаполнения.

Какой параметр передается на сервер и как должен выглядеть ответ JSON?

Должно быть, я что-то упустил, потому что как все остальные узнали, как это сделать? Кажется, что сайты обсуждают только код JavaScript на стороне клиента, а не примеры протоколов или серверов.

Мне нужно достаточно, чтобы получить самый простой удаленный пример работы.

6 ответов

Решение

Какой параметр передается на сервер

Вам нужно пройти request.term на ваш серверный код (из документации):

Объект запроса с единственным свойством, называемым "термин", который ссылается на значение в настоящее время в текстовом вводе.

В основном в вашем autocomplete код, у вас будет что-то вроде этого:

$("#autocomplete").autocomplete({
    // request.term needs to be passed up to the server.
    source: function(request, response) { ... }
});

и как должен выглядеть ответ JSON?

autocomplete виджет ожидает массив объектов JSON с label а также value свойства (хотя, если вы просто укажите value, он будет использоваться в качестве метки). Так что в простейшем случае вы можете просто вернуть данные, которые выглядят так:

[
    { label: 'C++', value: 'C++' }, 
    { label: 'Java', value: 'Java' }
    { label: 'COBOL', value: 'COBOL' }
]

Если вам нужно что-то более сложное, вы можете использовать success аргумент $.ajax Функция для нормализации данных, которые вы получаете до того, как автозаполнение получит их:

source: function( request, response ) {
    $.ajax({
        /* Snip */
        success: function(data) {
            response($.map( data.geonames, function( item ) {
                return {
                    label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
                    value: item.name
                }
            }));
         }
    });

Этот код взят из приведенного здесь примера (в целом это хороший пример работы ajax + autocomplete в более сложном сценарии).

По сути, при успешном выполнении ajax-запроса полученные данные нормализуются (с использованием $.map) к чему ожидает виджет автозаполнения.

Надеюсь, это поможет.

В дополнение к идеальному ответу Эндрю Уитакера, альтернативный метод $.map - это переопределение рендерера, пример которого показан на демонстрационной странице пользовательского интерфейса jQuery.

Я использовал эту функциональность, используя вызов JSON следующим образом:

JSON Response

{
   "Records": [
       {
           "WI_ID": "1",
           "Project": "ExampleProject",
           "Work_Item": "ExampleWorkItem",
           "Purchase_Order": "",
           "Price": "",
           "Comments": "",
           "Quoted_Hours": "",
           "Estimated_Hours": "",
           "Achieved": "False",
           "Used_Hours": "0"
       }
   ]
}

JQuery

$("#WorkItem").autocomplete({
      source: function(request, response){
           $.ajax({
               type: "POST",
               url: "ASPWebServiceURL.asmx/WorkItems",
               data: "{'Project_ID':'1'}",
               contentType: "application/json; charset=utf-8",
               dataType: "json",
               success: function (msg) {
                   response($.parseJSON(msg.d).Records);
               },
               error: function (msg) {
                   alert(msg.status + ' ' + msg.statusText);
               }
           })
       },

       select: function (event, ui) {
           $("#WorkItem").val(ui.item.Work_Item);
           return false;
       }
})
.data("autocomplete")._renderItem = function (ul, item) {
    return $("<li></li>")
    .data("item.autocomplete", item)
    .append("<a>" + item.Work_Item + "</a>")
    .appendTo(ul);
};

В этом примере функция _renderItem переопределяется, так что список результатов поиска (т. Е. Список, отображаемый под текстовым полем) заполняется с использованием атрибутов записей, которые я получил из ответа JSON.

Хотя это и не так просто, это позволяет вам извлечь некоторые довольно интересные вещи (например, используя несколько бит данных из ответа JSON)

Пока оба ответа являются сложными и вводящими в заблуждение, ключевым понятием jQuery UI Auto Complete является анонимная функция успеха, у вас есть возможность контролировать формат ответа JSON на стороне сервера из-за успешного обратного вызова AutoComplete. Метка, формат значения подходит для подражания, но вы можете определить любой формат JSON, который вам нужен, ключ в том, как вы определяете свою функцию успеха:

 <input id="refPaymentTerms" class="form-control">

$("#refPaymentTerms").autocomplete({
                source: function (request, response) {
                    $.ajax({
                        type: "POST",
                        url: "/admin/JobPaymentRefs",
                        dataType: "json",
                        data: {
                            term: request.termCode
                        },
                        error: function (xhr, textStatus, errorThrown) {
                            alert('Error: ' + xhr.responseText);
                        },
                        success: function (data) {
                            response($.map(data, function (item) {
                                return {
                                    label: item.label,
                                    value: item.value
                                }
                            }));
                        }
                    });
                }
            });

Контроллер MVC:

public JsonResult JobPaymentRefs()
    {
        var query = from REFTerm in _db.REFTerms
                     select new
                    {
                        label = REFTerm.TermCode,
                        value = REFTerm.TermCode
                    };
        //var refTerms = _db.REFTerms.Select(x => x.TermCode);

        return Json(query.ToArray());
    }

Здесь мы видим очень стандартное автоматическое связывание с бэкэндом ASP.NET.

Вы можете вернуть любой формат JSON, который вам нужен на стороне сервера, при условии, что вы правильно отобразите его в анонимном обратном вызове автозаполнения. Метка, пара имя-значение-значение достаточно подходит для большинства требований, но сделайте так, как вы будете на стороне сервера с вашим JSON, просто сопоставьте его правильно в обратном вызове автозаполнения.

Вам не нужно настраивать серверный скрипт, чтобы использовать автозаполнение пользовательского интерфейса jQuery. Вы можете указать функцию JavaScript в качестве source создавать пользовательские запросы (например, использовать POST или GET, использовать параметры строки запроса, ожидаемые сценарием на стороне сервера) и обрабатывать произвольные ответы (например, обрабатывать ответы XML).

Сказав это, когда вы используете строку в качестве source параметр, то:

[...] плагин автозаполнения ожидает, что эта строка будет указывать на ресурс URL, который будет возвращать данные JSON. Это может быть на том же хосте или на другом (должен предоставить JSONP). Плагин автозаполнения не фильтрует результаты, вместо этого в строку запроса добавляется поле термина, которое серверный сценарий должен использовать для фильтрации результатов. Например, если опция источника установлена ​​на http://example.com и пользователь вводит foo, запрос GET будет сделан для http://example.com?term=foo, Сами данные могут быть в том же формате, что и локальные данные, описанные выше.

Что касается "Данные могут быть в том же формате, что и локальные данные, описанные выше", будут работать следующие форматы JSON (или JSONP):

// no matching entries
[]

// array of strings
[
"Option 1",
"Option 2"
]

// array of objects with label property
[{
    "label": "Option 1"
}, {
    "label": "Option 2"
}]

// array of objects with value property
[{
    "value": "Option 1"
}, {
    "value": "Option 2"
}]

// array of objects with label and value properties
[{
    "label": "Option 1",
    "value": 1
}, {
    "label": "Option 2",
    "value": 2
}]

Для массивов объектов вы можете указать дополнительные свойства помимо метки и / или value, Все свойства будут доступны внутри обратных вызовов.

Следующий код работает для меня. Для этого нужны данные в кодировке JSON. Как только мы получаем данные, они изменяют их в соответствии с форматом автозаполнения jQuery, а также позволяют выбирать

var $url = "http://some-url/get-json";
//name is the id of the textbox where autocomplete needs to be shown
$('#name').autocomplete(
{ 
source: function(request,response)  
{ 

  //gets data from the url in JSON format
  $.get($url, function(data)
  {         
    obj = JSON.parse(data);   //parse the data in JSON (if not already)
    response($.map(obj, function(item)
    {
      return {
        label: item.full_name,
        value: item.full_name,
        id:item.id,
        email:item.email,
        phone:item.phone,
      }
    }
  ));        //end response
});          //end get
},
select:function(event, ui)
{ 
 console.log(ui.item.full_name);
 console.log(ui.item.email);
}   

}); //end of autocomplete

Следующее автозаполнение взято из https://jqueryui.com/autocomplete/

Демо-ссылка: https://jqueryui.com/resources/demos/autocomplete/remote-jsonp.html

Вот исходный код:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>jQuery UI Autocomplete - Remote JSONP datasource</title>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <link rel="stylesheet" href="/resources/demos/style.css">
    <style>
    .ui-autocomplete-loading {
        background: white url("images/ui-anim_basic_16x16.gif") right center no-repeat;
    }
    </style>
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script>
    $( function() {
        function log( message ) {
            $( "<div>" ).text( message ).prependTo( "#log" );
            $( "#log" ).scrollTop( 0 );
        }

        $( "#birds" ).autocomplete({
            source: function( request, response ) {
                $.ajax( {
                    url: "search.php",
                    dataType: "jsonp",
                    data: {
                        term: request.term
                    },
                    success: function( data ) {
                        response( data );
                    }
                } );
            },
            minLength: 2,
            select: function( event, ui ) {
                log( "Selected: " + ui.item.value + " aka " + ui.item.id );
            }
        } );
    } );
    </script>
</head>
<body>

<div class="ui-widget">
    <label for="birds">Birds: </label>
    <input id="birds">
</div>

<div class="ui-widget" style="margin-top:2em; font-family:Arial">
    Result:
    <div id="log" style="height: 200px; width: 300px; overflow: auto;" class="ui-widget-content"></div>
</div>


</body>
</html>

<!doctype html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>jQuery UI Autocomplete - Categories</title>
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
        <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
        <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
        <link rel="stylesheet" href="/resources/demos/style.css" />
        <style>
            .ui-autocomplete-category {
                font-weight: bold;
                padding: .2em .4em;
                margin: .8em 0 .2em;
                line-height: 1.5;
            }
            body {
                font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif";
                font-size: 62.5%;
            }
        </style>
        <script>
            $.widget("custom.catcomplete", $.ui.autocomplete, {
                _renderMenu : function(ul, items) {
                    var that = this, currentCategory = "";
                    $.each(items, function(index, item) {
                        if (item.category != currentCategory) {
                            ul.append("<li class='ui-autocomplete-category'>" + item.category + "</li>");
                            currentCategory = item.category;
                        }
                        that._renderItemData(ul, item);
                    });
                }
            });
        </script>
        <script>
            $(function() {
                $("#search").catcomplete({
                    delay : 0,
                    source : function(request, response) {
                        $.ajax({
                            url : "search",
                            dataType : "json",
                            data :"searchText=hk",
                            success : function(data) {
                                response(data);
                            } //success
                        });
                    }
                });
            });
        </script>
    </head>
    <body>enter code here
        <label for="search">Search: </label>
        <input id="search" />
    </body>
</html>
Другие вопросы по тегам