2012-11-26 4 views
9

У меня есть несколько полей Kendo AutoComplete, связанных с удаленными данными (сотни возможностей, поэтому DropDownList не является вариантом).Kendo AutoComplete - заставить пользователей делать правильный выбор

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

Я также получаю дополнительные данные, которые возвращаются из источника данных, например.

$("#station").kendoAutoComplete({ 
    dataSource: stationData, 
    minLength: 2, 
    dataTextField: 'name', 
    select: function(e){ 
     var dataItem = this.dataItem(e.item.index()); 
     console.dir(dataItem); 
    } 
}); 

Я делаю дополнительный материал с данными dataItem, и он должен быть правильным выбором.

Благодаря

РЕШИТЬ: Я думаю, что я, возможно, чрезмерно усложнять вещи. Ответ довольно прост и размещен ниже.

ответ

14
var valid; 
$("#staton").kendoAutoComplete({ 
    minLength: 2, 
    dataTextField: "name", 
    open: function(e) { 
    valid = false; 
    }, 
    select: function(e){ 
    valid = true; 
    }, 
    close: function(e){ 
    // if no valid selection - clear input 
    if (!valid) this.value(''); 
    }, 
    dataSource: datasource 
}); 
+0

Используя этот метод, если пользователь не делает правильный выбор, все, что они набрали в автозаполнение, очищается 'onblur', что является результатом, который я получил после – Mat

+0

. В моих тестах" close "не запускается, если пользователь вводил значение, которое возвращало 0 элементов с сервера. То есть, я набираю «1234 ..», который ничего не извлекает с сервера, а затем выходит из текстового поля, событие «закрыть» не запускается :-( – Dror

+0

Это неправильный ответ. Вы должны использовать «изменение», событие, а не «закрыть». – ataravati

1

Может быть, вы можете сделать свою собственную проверку с помощью blur события:

$("#station").blur(function() { 
    var data = stationData, 
     nbData = data.length, 
     found = false; 

    for(var iData = 0; iData < nbData; iData++) { 
     if(this.value === data[iData].yourfieldname) // replace "yourfieldname" by the corresponding one if needed 
      found = true; 
    } 
    console.log(found); 
}); 

Вы можете проверить this fiddle.

+0

Спасибо Самуэль, я думаю, что могу probebly работать с чем-то вроде этого. У этого есть проблема, хотя в том, что 'found' возвращает' false' на select, прежде чем он вернет 'true' при размытии (не уверен, почему). – Mat

+0

Я не понимаю, что «найдено» - это переменная, которую я установил и существует только в области события размытия ... Возможно, вы добавили тест с той же переменной на событие select? если это так, это нормально: выбор происходит до того, как поле автозаполняется ... –

+0

Привет. Я еще ничего не реализовал - это всего лишь комментарий к вашей скрипке. В консоли Chrome возвращается false, как только будет сделан выбор. Истина затем возвращается, когда вы выходите из поля ввода. – Mat

0

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

Для этого перехватите событие изменения автозаполнения Kendo и сравните текущее значение ввода пользователя с элементами из отфильтрованного списка.

0

Надеется, что это помогает,

$("#autocomplete_id").val(""); 

$("#autocomplete").kendoAutoComplete({ 
    dataSource: datasource, 
    minLength: 1, 
    dataTextField: "catname", 
    dataValueField:"id", 
    select: function(e) {     
     var dataItem = this.dataItem(e.item.index());     
     $("#autocomplete_id").val(dataItem.id); 
    }, 
    dataBound: function(e){ 
     $("#autocomplete_id").val(""); 
    } 
}); 

FYI, autocomplete_id скрытого поле для хранения значения автозаполнения. - Иногда мы хотели бы иметь dataValueField, отличный от dataTextField. Таким образом, он служит своей цели.

В этом вы можете получить значение автозаполнения «id» из элемента autocomplete_id, который является dataValueField с сервера.

В привязке данных значения его значения равны нулю, а по выбору ему присваивается значение «id».

+0

Это не отвечает на вопрос - он по-прежнему позволяет пользователям вводить все, что им нравится, в автозаполнение и не заставляет их выбирать допустимый вариант. – Mat

8

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

  1. инициализации переменной действует как ложь:

    вар действует = ложь;

  2. Проверьте, не действует отбор в случае изменения, но не близко:

    ... 
    change: function(e){ if (!valid) this.value(''); } 
    
+2

это должен быть принятый ответ. – Jakobovski

+0

Согласитесь с @Jakobovski, это намного лучше. Если пользователь что-то замалчивает и список закрывается, решение Mat вызовет событие закрытия и сразу очистит поле. Эта модификация очищает вход только в реальном событии blur и позволяет пользователю выполните поиск по списку. –

+0

Как я уже говорил, событие «закрыть» не запускается, когда пользователь вводит значение, которое не возвращает никаких «ударов» с сервера. Таким образом, это лучшее решение. – Dror

0

Хотя accepted answer работ, это не самое лучшее решение.

Предоставленное решение не учитывает, вводит ли пользователь значение, даже если виджет «Автозаполнение» кендо запускает событие open. В результате введенное значение не принудительно, и поэтому запись/выбор недействительны.

Мой подход предполагает, что приложение работает в MVC и массив передается в ViewData. Но это можно изменить в соответствии с вашей средой.

Мой подход:

var validSelect, isSelected; 
$("#staton").kendoAutoComplete({ 
    minLength: 2, 
    filter: "startswith", 
    dataTextField: "name", 
    filtering: function(e) { 
     validSelect = false; 
     dataArr = @Html.Raw(Json.Encode(ViewData["allStatons"])); 
     // for loop within the ViewData array to find for matching ID 
     for (var i = 0; i < dataArr .length; i++){ 
      if (dataArr[i].ID.toString().match("^" + $("#staton").val())) { 
       validSelect = true; 
       break; 
      } 
     } 

     // if value entered was not found in array - clear input 
     if (!validSelect) $("#staton").val(""); 
    }, 
    select: function(e){ 
     isSelected = true; 
    }, 
    close: function(e){ 
     // if selection is invalid or not selected from the list - clear input 
     if (!validSelect || !isSelected) $("#staton").val(""); 
    }, 
    dataSource: datasource 
}); 

Как вы можете видеть, этот подход требует массив со стороны сервера на нагрузке, так что он может соответствовать во время фильтрации события виджета.

0

Ответ на сообщение OP, в дополнение к ответу, предложенному @ Rock'n'muse, безусловно, является хорошим предложением, но оба не имеют важного и желаемого функционального аспекта.

При использовании раствора, данное @Mat и реализации change -vice- close предложение от @ Rock'n'muse, набранное в значение действительно очищает от виджета, если выбор не сделан из фильтруемого источника данных. Отлично; однако, если пользователь вводит что-то действительное и выбирает значение из отфильтрованного списка, затем помещает курсор в конец значения и набирает что-то, что сейчас делает недействительным значение (не возвращает никаких действительных выборов из источник данных), введенное значение не удаляется из виджета.

Что происходит, то значение isValid остается true, если ранее введенное (и действительное) значение должно быть изменено. Решением этого является установка isValid на false, как только будет инициировано событие фильтрации. Когда пользователь изменяет введенное значение, виджет пытается отфильтровать источник данных в поисках введенного значения. Установка isValid на false, как только запускается событие filter, обеспечивает «чистый сланец» для события change, как это было предложено решением от @ Rock'n'muse.

Поскольку мы устанавливаем isValid ложь, как только filtering событие срабатывает, мы не должны делать это в open случае (как источника данных фильтрации должно произойти до того, как пользователь никогда не увидит возможность выбора) , Из-за этого связь @была удалена из решения @ Mat. Это также означает, что первоначальное присвоение false по объявлению isValid является излишним, но присвоение переменной при объявлении всегда является хорошей идеей.

Ниже раствор из @Mat вместе с предложениями от @ Rock'n'muse и с filtering реализации применяются:

var isValid = false; 
$("#staton").kendoAutoComplete({ 
    minLength: 2, 
    dataTextField: "name", 
    select: function() { 
     valid = true; 
    }, 
    change: function (e) { 
     // if no valid selection - clear input 
     if (!valid) { 
      e.sender.value(""); 
     } 
    }, 
    filtering: function() { 
     valid = false; 
    }, 
    dataSource: datasource 
}); 

В качестве приложения, с использованием привязки установить и оценить на select событие простое логическое значение, поскольку @Mat предлагает много чище, проще и быстрее, чем использование jQuery $.each(...) на источнике данных, чтобы убедиться, что введенное значение соответствует фактическому элементу источника данных в событии change. Это была моя первая мысль при работе над решением, прежде чем я нашел решение от @Mat (на этой странице), и такова моя аргументация за голосование за его решение и его вопрос.

0

Я нашел это на сайте Telerik, просто используя событие изменения. Для меня это лучше всего работает. Я добавил проверку «value ===». Это поймает, когда пользователь «очистит» выбор.

Here's the link to the full article.

 $("#countries").kendoAutoComplete({ 
     dataSource: data, 
     filter: "startswith", 
     placeholder: "Select country...", 
     change: function() { 
      var value = this.value(); 
      if (value === '') return; 
      var found = false; 
      var data = this.dataSource.view(); 

      for(var idx = 0, length = data.length; idx < length; idx++) { 
      if (data[idx] === value) { 
       found = true; 
       break; 
      } 
      } 

      if (!found) { 
      this.value(""); 
      alert("Custom values are not allowed"); 
      } 
     } 
     }); 
Смежные вопросы