2008-11-20 18 views
49

Ich suchte überall auf dieser Website und im Internet nach einem guten und einfachen Beispiel für Autovervollständigung mit jQuery und ASP.NET. Ich wollte die von Autocomplete verwendeten Daten mit einem Webservice versehen (und werde das wahrscheinlich als nächstes machen). In der Zwischenzeit habe ich diese Arbeit, aber es scheint ein wenig hacky ...jQuery Autocomplete und ASP.NET

In meiner Seite habe ich ein Textfeld:

<input id="txtSearch" type="text" /> 

ich jQuery Autocomplete bin mit eingesetzter pro ihrem Beispiel:

<link rel="stylesheet" href="js/jquery.autocomplete.css" type="text/css" /> 
<script type="text/javascript" src="js/jquery.bgiframe.js"></script> 
<script type="text/javascript" src="js/jquery.dimensions.pack.js"></script> 
<script type="text/javascript" src="js/jquery.autocomplete.js"></script> 

Hier ist, wo es beginnt hacky zu bekommen ... ich nenne eine Seite anstelle eines Webservice:

<script type="text/javascript"> 
    $(document).ready(function(){ 
     $("#txtSearch").autocomplete('autocompletetagdata.aspx'); 
    });  
    </script> 

In die Seite zog ich alle HTML und nur diese haben (sonst zeigen verschiedene HTML-Bits in dem Autocomplete-Drop-Down-up):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="autocompletetagdata.aspx.cs" Inherits="autocompletetagdata" %> 

Und in meinem autocompletetagdata.aspx, ich SubSonic abfragen verwenden, Format und Rück Daten aus der Datenbank (einem Datenelement pro Zeile):

protected void Page_Load(object sender, EventArgs e) 
{ 
    // Note the query strings passed by jquery autocomplete: 
    //QueryString: {q=a&limit=150&timestamp=1227198175320} 

    LookupTagCollection tags = Select.AllColumnsFrom<LookupTag>() 
     .Top(Request.QueryString["limit"]) 
     .Where(LookupTag.Columns.TagDescription).Like(Request.QueryString["q"] + "%") 
     .OrderAsc(LookupTag.Columns.TagDescription) 
     .ExecuteAsCollection<LookupTagCollection>(); 

    StringBuilder sb = new StringBuilder(); 

    foreach (LookupTag tag in tags) 
    { 
     sb.Append(tag.TagDescription).Append("\n"); 
    } 

    Response.Write(sb.ToString()); 
} 

Wenn Sie nicht über eine LIKE Abfrage tun, dann gibt es alles, was ein Spiel für das Zeichen enthält (n) geben - zum Beispiel, das Eingeben von "a" umfasst "Ask" und "Answer" sowie "March" und "Mega". Ich wollte nur, dass es mit einem Match beginnt.

Wie auch immer, es funktioniert und es ist ziemlich einfach einzurichten, aber gibt es einen besseren Weg?

+0

Dank djuth funktioniert diese groß und ist sehr einfach! Ich muss zugeben, dass es ziemlich einschränkend ist, zum Beispiel würde ich es lieben, wenn es einen Personalnamen automatisch vervollständigt und dann eine staffID zurückgibt, aber ich kann wahrscheinlich mit dem experimentieren, was hinzugefügt und geparst wurde. –

+1

Dies ist jetzt veraltet und integriert mit JQuery UI - http://www.learningjquery.com/2010/06/autocomplete-migration-guide zeigt, wie zu migrieren, nicht viel zu es! – Duncan

Antwort

32

Ich habe kürzlich Autocomplete implementiert, und es sieht ziemlich ähnlich aus. Ich benutze ein Ashx (Generic Handler) anstelle des Aspx, aber es ist im Grunde der gleiche Code im Code dahinter.

die Ashx Verwendung, wird es in etwa so aussehen:

<script type="text/javascript"> 
    $(document).ready(function(){ 
     $("#txtSearch").autocomplete('autocompletetagdata.ashx'); 
    });  
</script> 

[WebService(Namespace = "http://www.yoursite.com/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
public class AutocompleteTagData : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     // Note the query strings passed by jquery autocomplete: 
     //QueryString: {q=a&limit=150&timestamp=1227198175320} 

     LookupTagCollection tags = Select.AllColumnsFrom<LookupTag>() 
      .Top(context.Request.QueryString["limit"]) 
      .Where(LookupTag.Columns.TagDescription).Like(context.Request.QueryString["q"] + "%") 
      .OrderAsc(LookupTag.Columns.TagDescription) 
      .ExecuteAsCollection<LookupTagCollection>(); 

     foreach (LookupTag tag in tags) 
     { 
      context.Response.Write(tag.TagDescription + Environment.NewLine); 
     } 
    } 

    public bool IsReusable 
    { 
     get 
     { 
      return false; 
     } 
    } 
} 
+1

Hatten Sie Probleme mit den Berechtigungen in IIS für die Aschex-Datei? Ich habe diese Methode verwendet, und wenn ich die Anwendung auf IIS 6 bereitstellen, kann der Browser nicht auf die Aschx-Datei zugreifen. – Gromer

+0

Ich denke, die neue jQuery AutoComplete verwendet die Eigenschaft "term" anstelle von "limit", ohne dass dieser Code auf einem anderen Plug-in basiert. Von jQuery-API-Dokumenten: * "Ein Anforderungsobjekt mit einer einzigen Eigenschaft namens" term ", die sich auf den Wert in der Texteingabe bezieht. Wenn der Benutzer z. B." new yo "in einem Stadtfeld eingegeben hat, wird der Autocomplete-Begriff verwendet wird gleich "new yo" sein. * http://jqueryui.com/demos/autocomplete/#remote – atconway

+0

'limit' ist die maximale Anzahl von Ergebnissen, die zurückgegeben werden. Es kann jedoch' term' anstelle von 'q' gesendet werden, was Dieses Beispiel verwendet ... – bdukes

6

Der Web-Dienst oder ein WCF-Dienst Sie für eine bessere Schnittstelle das Potential geben. Beide können auch für die JSN-Serialisierung eingerichtet werden.

Da ich eine WCF-Klasse nehme, während ich schreibe (ich bin in einer Pause, wirklich!), Skizziere ich die WCF-Methode.

[OperationContract] 
[WebInvoke(RequestFormat=WebMessageFormat.Json, 
      ResponseFormat=WebMessageFormat.Json)] 
public LookupTagCollection LookupTags(int limit, string q) 
{ 
    return Select.AllColumnsFrom<LookupTag>() 
        .Top(limit) 
        .Where(LookupTag.Columns.TagDescription) 
        .Like(q+ "%") 
        .OrderAs(LookupTag.Columns.TagDescription) 
        .ExecuteAsCollection<LookupTagCollection>();  
} 

LookupTagCollection muss serialisierbar sein.

+0

Unglücklicherweise erwartet das Autocomplete-Widget JSON nicht, es will nur Text, jedes Element in einer neuen Zeile, aber für JSON-Sachen, die nett aussehen. Mit welcher URL würdest du darauf zugreifen? – bdukes

10

Ich habe dies gerade auf eine andere Frage geschrieben, aber Sie können die Analysefunktion auf dem jQuery-Autocomplete-Plug-in überschreiben, um jede Ausgabe zu unterstützen.

Beispiel:

$("#<%= TextBox1.ClientID %>").autocomplete("/Demo/WebSvc.asmx/SuggestCustomers", { 
     parse: function(data) { 
      var parsed = []; 

      $(data).find("string").each(function() { 
       parsed[parsed.length] = { 
        data: [$(this).text()], 
        value: $(this).text(), 
        result: [$(this).text()] 
       }; 
      }); 
      return parsed; 
     }, 
     dataType: "xml" 
    }); 

dies erwartet, dass alle in XML ein String-Array ist ... Sehr einfach zu tun ... Wenn Ihr SubSonic verwenden, sollten Sie die RESTHandler Check-out (Es ist eine versteckte GEM ist !! !), es unterstützt grundlegende Abfragen für alle Ihre Objekte und kann JSON/XML zurückgeben. Hier ist ein Beispiel Abfrage es ...

/Demo/services/Customers/list.xml?CustomerName=JOHN

Wenn Sie die Liste ändern.XML zu list.json wird die Ergebnisse in JSON ändern. Die obige Anfrage gibt die stark typisierte Entität "Kunde" zurück. Sie können die Parameter ändern zu unterstützen LIKE, nicht wie, etc ... Sehr leistungsfähige und all die sanitären Anlagen ist arleady getan ...

Hier ist ein Video drauf: http://subsonicproject.com/tips-and-tricks/webcast-using-subsonic-s-rest-handler/

+0

Das ist Die eigentliche Antwort für die Verarbeitung von XML mit einem Name/Wert-Paarung Die obige markierte Antwort ist nur für den Anzeigetext - Sie können keine Wert-Paarung festlegen/erhalten. – eduncan911

4

JQuery 1.8 Automatische Vervollständigung verwendet „-Begriff "nicht" q "wie der querystring param. Dies ist die kurze und süße Version, die ich implementiert habe. Hoffe, das hilft jemandem.

Javascript:

$(function() { 
    $("#autocomplete").autocomplete({ 
     source: "/pathtohandler/handler.ashx", 
     minLength: 1, 
     select: function (event, ui) { 
      $(this).val(ui.item.value); 
     } 
    }); 
}); 

ASHX Handler:

public class SearchHandler : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     var term = context.Request.QueryString["term"].ToString(); 

     context.Response.Clear(); 
     context.Response.ContentType = "application/json"; 

     var search = //TODO implement select logic based on the term above 

     JavaScriptSerializer jsSerializer = new JavaScriptSerializer(); 
     string json = jsSerializer.Serialize(search); 
     context.Response.Write(json); 
     context.Response.End(); 
    } 

    public bool IsReusable 
    { 
     get 
     { 
      return false; 
     } 
    } 
}