2012-11-26 10 views
9

Ich habe ein paar Kendo AutoComplete-Felder mit entfernten Daten verknüpft (Hunderte von Möglichkeiten, so DropDownList ist keine Option).Kendo AutoComplete - Erzwinge die Auswahl der Benutzer

Wie kann ich Benutzer zwingen, eine Auswahl aus der angezeigten Liste zu treffen?

Ich lade auch die zusätzlichen Daten, die von der Datenquelle zurückgegeben wird, z.

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

Ich mache zusätzliche Sachen mit den Daten in dataItem und es muss eine gültige Auswahl sein.

Dank

GELÖST: Ich glaube, ich war vielleicht zu verkomplizieren Dinge. Die Antwort ist ziemlich einfach und wird unten veröffentlicht.

Antwort

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

Wenn ein Benutzer keine gültige Auswahl trifft, wird, was auch immer sie in die AutoVervollständigung eingegeben haben, "Onblur" gelöscht, was das Ergebnis ist, nach dem ich bin – Mat

+0

In meinen Tests die " close "Ereignis wird nicht ausgelöst, wenn der Benutzer einen Wert eingegeben hat, der 0 Elemente vom Server zurückgegeben hat. Das heißt, ich fange an "1234 .." einzugeben, was nichts vom Server holt und dann das Textfeld verlässt, das "close" -Ereignis wird nicht ausgelöst :-( – Dror

+0

Dies ist nicht die richtige Antwort. Sie sollten die "Änderung" verwenden Ereignis, nicht "close". – ataravati

1

Vielleicht können Sie Ihre eigene Validierung, indem Sie das blur Ereignis mit:

$("#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); 
}); 

Sie this fiddle überprüfen können.

+0

Dank Samuel, ich glaube, ich probebly mit so etwas wie das funktionieren kann. Es hat allerdings ein Problem, da "gefunden" bei Auswahl "falsch" zurückgibt, bevor es bei Unschärfe "wahr" zurückgibt (nicht sicher warum). – Mat

+0

Ich verstehe nicht 'gefunden' ist die Variable, die ich gesetzt habe und nur im Bereich des Blur-Ereignisses existiert ... Vielleicht hast du einen Test mit der gleichen Variablen für das select-Ereignis hinzugefügt? Wenn dies der Fall ist, ist es normal: Auswahl tritt auf, bevor das Feld automatisch vervollständigt wird ... –

+0

Hi. Ich habe noch nichts umgesetzt - das ist nur ein Kommentar zu deiner Geige. In der Chrome-Konsole wird false zurückgegeben, sobald eine Auswahl getroffen wurde. True wird dann zurückgegeben, wenn Sie aus dem Eingabefeld klicken. – Mat

0

Sie höchstwahrscheinlich einige benutzerdefinierte Logik benötigen, die jeden Tastendruck nach dem min Länge von zwei Symbolen abfangen überschritten wird, und die Option verhindern, dass ein Zeichen einzugeben, die die Zeichenfolge nicht Benutzer macht jede der Elemente aus dem Match Autocomplete-Liste.

Abfangen des Änderungsereignisses der Kendo-Autocomplete und Vergleichen des aktuellen Eingabewerts des Benutzers mit den Elementen aus der gefilterten Liste.

0

hoffe, das hilft,

$("#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, ist autocomplete_id ein verstecktes Feld, um den Wert der Autovervollständigung zu speichern. - Manchmal möchten wir das dataValueField anders als dataTextField haben. Also, es erfüllt seinen Zweck.

In diesem können Sie den Wert der Autocomplete "ID" aus dem Element Autocomplete_id - das ist DataValueField von der Server-Seite.

In datengebunden sind seine Werte auf null gesetzt, und bei Auswahl wird ihm der Wert "id" zugewiesen.

+0

Das beantwortet nicht wirklich die Frage - es erlaubt Benutzern immer noch, was sie wollen, in die AutoVervollständigung zu schreiben und zwingt sie nicht, eine gültige Wahl zu wählen. – Mat

8

Mit dieser Methode können Benutzer in die AutoVervollständigen-Liste eingeben, wenn sie nicht geöffnet wird. Es gibt zwei Korrekturen dieses Problem zu beheben:

  1. initialisieren Variable gültig als falsch:

    var gültig = false;

  2. prüfen, wenn keine gültige Auswahl in Änderungsereignis, aber nicht in der Nähe:

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

das sollte die angenommene Antwort sein. – Jakobovski

+0

Vereinbaren Sie mit @Jakobovski, das ist viel besser.Wenn ein Benutzer etwas falsch schreibt und die Liste schließt, löst Mat Lösung das Schließen-Ereignis und löscht das Feld sofort.Diese Änderung löscht die Eingabe nur auf das echte Blur-Ereignis und lässt den Benutzer Durchsuche die Liste –

+0

Wie oben erwähnt, wird das Ereignis "close" nicht ausgelöst, wenn der Benutzer einen Wert eingibt, der keine "Treffer" vom Server zurückgibt. Das ist also eine bessere Lösung. Dror – Dror

0

Obwohl die accepted answer Werke, ist es nicht die beste Lösung ist.

Die angegebene Lösung wird nicht berücksichtigt, wenn der Benutzer einen Wert eingibt, bevor selbst das Kendo AutoComplete-Widget das offene Ereignis auslöst. Im Ergebnis wird der eingegebene Wert nicht erzwungen und daher ist die Eingabe/Auswahl ungültig.

Mein Ansatz geht davon aus, dass die Anwendung in läuft MVC und das Array in Viewdata geben. Dies kann jedoch entsprechend Ihrer Umgebung geändert werden.

Mein Ansatz:

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 
}); 

Wie Sie sehen können, ist dieser Ansatz erfordert die Anordnung von der Serverseite auf Last, so dass es während des Filterereignis des Widgets bieten kann.

0

Die Antwort des OP gepostet, zusätzlich zu der Antwort von @ Rock'n'muse vorgeschlagen sind definitiv gute Vorschläge, aber beide verpassen einen wichtigen und gewünschten funktionalen Aspekt.

Wenn die Lösung durch @Mat gegeben Nutzung und den change -vice- close Vorschlags von @ Rock'n'muse, der eingegebenem Wert Implementierung löscht zwar aus dem Widget, wenn keine Auswahl aus der gefilterten Datenquelle hergestellt wird. Das ist toll; Wenn der Benutzer jedoch etwas Gültiges eingibt und einen Wert aus der gefilterten Liste auswählt, setzt dann den Cursor an das Ende des Werts und gibt einen Wert ein, der den Wert ungültig macht (gibt keine gültige Auswahl aus dem Datenquelle), wird der eingegebene Wert nicht vom Widget gelöscht.

Was passiert ist, dass der isValid Wert true bleibt, wenn der zuvor eingegebene (und gültige) Wert geändert werden sollte. Die Lösung besteht darin, isValid auf false zu setzen, sobald das Filterereignis ausgelöst wird. Wenn der Benutzer den eingegebenen Wert ändert, versucht das Widget, die Datenquelle bei der Suche nach dem eingegebenen Wert zu filtern. Das Setzen von isValid auf false, sobald das Ereignis filter ausgelöst wird, sorgt für eine "saubere Weste" für das Ereignis , wie von der Lösung von @ Rock'n'muse vorgeschlagen.

Weil wir isValid auf false sind einstellen, sobald das filtering Ereignis ausgelöst wird, müssen wir nicht tun, so im Fall open (als Datenquelle Filterung erfolgen muss, bevor der Benutzer jemals eine Option wählen) . Aus diesem Grund wurde die Ereignisbindung open aus der @ Mat-Lösung entfernt. Dies bedeutet auch, dass die anfängliche Zuweisung von false bei der Deklaration von isValid überflüssig ist, aber eine variable Zuweisung bei der Deklaration ist immer eine gute Idee.

Im Folgenden finden Sie die Lösung von @Mat zusammen mit den Vorschlägen von @ Rock'n'muse und mit der filtering Implementierung angewandt:

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 
}); 

Als Nachtrag, das select Ereignis mit Bindung ein setzen und bewerten Ein einfacher boolescher Wert wie @Mat schlägt viel sauberer, einfacher und schneller als mit einem jQuery $.each(...) auf der Datenquelle, um sicherzustellen, dass der eingegebene Wert einem tatsächlichen Element der Datenquelle innerhalb der change Ereignis entspricht. Dies war mein erster Gedanke, eine Lösung zu entwickeln, bevor ich die Lösung von @Mat (diese Seite) gefunden habe, und dies ist meine Argumentation für die Abstimmung seiner Lösung und seiner Frage.

0

Ich habe dies auf der Telerik-Website gefunden, indem ich nur das Change-Event verwendet habe. Für mich funktioniert das am besten. Ich habe den "value === ''" Check hinzugefügt. Dies wird abgefangen, wenn der Benutzer die Auswahl "löscht".

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"); 
      } 
     } 
     }); 
Verwandte Themen