select2 удаленные данные: заполнить с помощью конечной точки Web API 2

Согласно заголовку, я использую последнее поле выбора select2 на странице HTML5 и, используя их пример, я делаю вызов созданной мной конечной точке Web API 2.

В целях тестирования конечная точка просто создает коллекцию тегов и возвращает результат в виде HttpResponseMessage. Вот некоторый код для визуализации всего этого:

Объект тега

public class TagData
{
    public string Id { get; set; }
    public string Text { get; set; }
}

Модель:

public class TagsModel
{
    public IEnumerable<TagData> Tags { get; set; }
}

Действие контроллера в проекте Web API 2:

    public IHttpActionResult Get()
    {
        var tags = new TagsModel()
        {
            Tags = new List<TagData>
            {
                new TagData()
                {
                    Id = "1",
                    Text = "Tag1"
                },
                new TagData()
                {
                    Id = "2",
                    Text = "Tag2"
                }
            }
        };
        return Ok(tags);
    }

Я запустил модульный тест, и все работает, также запуск теста в Fiddler4 с использованием композитора возвращает следующий ответ JSON:

{"Tags":[{"Id":"1","Text":"Tag1"},{"Id":"2","Text":"Tag2"},{"Id":"3","Text":"Tag3"}}]}

На странице HTML5 я добавил стандартный html-элемент select2:

    <select class='s2-search-box form-control' multiple='multiple'></select>

Идея здесь состоит в том, чтобы привязать элемент управления select2 к удаленным данным, а затем использовать функцию тегирования, чтобы пользователь мог найти тег, выбрать его и повторить, чтобы это было сделано с помощью этого вызова ajax:

    $(document).ready(function () {

        $(".s2-search-box").select2({
            ajax: {
                url: "http://localhost:54850/api/s2demo",
                dataType: 'json',
                delay: 250,
                data: function (params) {
                    return {
                        q: params.term, // search term
                        page: params.page
                    };
                },
                processResults: function (data, page) {
                    // parse the results into the format expected by Select2.
                    // since we are using custom formatting functions we do not need to
                    // alter the remote JSON data
                    return {
                        results: data.Tags
                    };
                },
                cache: true
            }
        });
    });

Пока все хорошо, мои модульные тесты работают, и когда я использовал Firebug для проверки вызова ajax, я вижу, что данные возвращаются в правильном формате, и я могу отображать коллекцию data.Tags, поэтому я знаю, что данные есть, однако фактическое Выпадающий список select2 отображает список «неопределенных» элементов и фактически не отображает данные, которые я хочу, и не позволяет мне создавать теги из этих вариантов.

В качестве примечания я также пробовал это:

    $(".s2-search-box").select2({
        ajax: {
            url: "http://localhost:54850/api/s2demo",
            dataType: "json",
            type: "GET",
            data: function (params) {

                var queryParameters = {
                    term: params.term
                }
                return queryParameters;
            },
            processResults: function (data) {
                return {
                    results: $.map(data, function (item) {
                        return {
                            text: item.Text,
                            id: item.Id
                        }
                    }),
                    pagination: {
                        more: data.more
                    }
                };
            }
        }
    });

Это работает тем, что я могу создать теги, чтобы они отображались в элементе управления select2 как:

тег1[x] тег2[x]

Однако выпадающий список отображается постоянно.

Я использую последнюю версию 4.0.2 библиотеки select2.

Заранее спасибо.

T


person Trevor    schedule 18.05.2016    source источник


Ответы (1)


Решил это, наконец, после нескольких серьезных часов, в основном из-за того, что информация была разбросана и из-за новой версии select2, которая сейчас не так широко используется.

Поэтому мне пришлось внести несколько изменений, первое из которых было в контроллере, чтобы позволить мне делать запросы GET и POST (есть лучшие способы сделать это, но для прототипирования это работает):

    [AcceptVerbs("GET","POST")]
    public IHttpActionResult TagLookup([FromBody]string value)
    {
        var tags = TagsModel;

        var results = new TagsModel();
        var tagsList = new List<TagData>();
        var i = 0;

        foreach (var m in tags.Tags)
        {
            i++;
            if (m.Text.Contains(value))
            {
                tagsList.Add(new TagData()
                {
                    Id = i.ToString(),
                    Text = m.Text
                });
            }
        }

        results.Tags = tagsList;

        return Ok(results);
    }

Блок кода достаточно прост, я возвращаю модель, содержащую набор тегов (сущность TagaData), однако отличается декоратором действия, атрибутом AcceptVerbs, который принимает запросы GET и POST от любого клиента.

Также я добавил атрибут параметра [FromBody], который заставляет веб-API считывать простой тип из тела запроса (для сложных типов вы должны использовать FromUri).

Затем я изменил вызов Ajax на странице HTML следующим образом:

    $(document).ready(function () {

        $(".s2-search-box").select2({
            ajax: {
                url: "http://localhost:54850/api/s2demo",
                contentType: "application/x-www-form-urlencoded; charset=UTF-8",
                type: 'POST',
                dataType: 'json',
                delay: 250,
                data: function(params) {
                    return '=' + params.term; // search term
                },
                processResults: function(data) {
                    return {
                        results: $.map(data.Tags, function(item) {
                            return {
                                text: item.Text,
                                id: item.Id
                            }
                        })
                    };
                },
                cache: true
            }
        });
    });

Итак, важно отметить здесь функцию, которая передает параметр в отправляемую полезную нагрузку данных, но что здесь есть для Web API 2, так это символ '=', который мне пришлось прикрутить к возврату:

return '=' + params.term; 

Это необходимо, чтобы веб-API понял, что делать с параметром, иначе он будет проигнорирован.

Раздел «processResults:» помечает массив тегов и привязывает данные к элементу управления select2, предоставляя мне заполненный раскрывающийся список (если были возвращены какие-либо данные, соответствующие переданному термину).

Также теперь я могу выбрать тег, и он появится в select2 как тег в поле ввода. Я сделал это, убедившись, что множественный атрибут включен в элемент управления select2 html:

<select class="s2-search-box form-control" multiple="multiple"></select>

Это разобрало это для меня, надеюсь, прольет свет на всех, кто чешет голову. Перейдем к следующей части: берем теги в поле select2 и отправляем их другому действию контроллера веб-API.

person Trevor    schedule 21.05.2016