Autocomplete Input Razor Page

Aus der Reihe- SPA Framework freie Websites- kommt heute ein Anwendungsfall eines Eingabefeldes mit Vorschlagsliste.

image

Dafür werden folgende Technologien eingesetzt

  • JQuery Autocomplete Plugin
  • Razor Page Handler
  • Singleton Data Service
  • Json Parser

 

Wie üblich starten wir mit einem Visual Studio 2019 asp.net core 3 Projekt.

Installieren sie per Nuget das Paket System.Text.Json.

image

Kopieren Sie die Javascript und CSS Datei in Ihr Web Projekt. Am besten beide in das wwwroot Lib Verzeichnis. Tipp- die idente Benennung von css und js mit jquery.autocomplete.

Die Referenzen werden Pages/shared/_layout.cshtml eingefügt.

   1:      <link href="~/lib/jquery.autocomplete.css" rel="stylesheet" />
   2:  </head>
   3:  <body>

 

   1:     <script src="~/lib/jquery.autocomplete.js"></script>
   2:      @RenderSection("Scripts", required: false)
   3:  </body>
   4:  </html>

Erzeugen Sie nun ein Verzeichnis Models und Services im Root der Webanwendung auf gleicher Hierarchieebene wie Pages.

image

Fügen Sie im Visual Studio Projekt in wwwroot eine JavaScript Datei mit dem Namen cars.json hinzu. Den Inhalt können Sie per Copy Paste von der Url einfügen. Falls eigene Hersteller listen wollen im folgenden JSON Format.

   1:  [{"name": "BMW"
   2:  }, {
   3:  "name": "VOLKSWAGEN"
   4:  },

Als nächstes wird im Model Verzeichnis eine Klasse car.cs erzeugt um später eine generische Liste mit Herstellern füllen zu können.

   1:    public class Car
   2:      {
   3:          public string name { get; set; }
   4:      }

Für den Datenzugriff erzeugen Sie im Services Verzeichnis eine Datei CarService. Dieser hält die Fahrzeuge statisch nach Start der Web Anwendung. Gefüllt werden die Daten automatisch im Konstruktor. Dazu kommt der neue JSON Serialisierer (statt JSON.NET) aus asp.net core 3 zum Einsatz

   1:  public class CarService
   2:  {
   3:    public List<Car> CarListe { get; set; }
   4:    public CarService()
   5:      {
   6:              var options = new JsonSerializerOptions
   7:              {
   8:                  AllowTrailingCommas = true
   9:         };
  10:         var pfad = AppDomain.CurrentDomain.GetData("WWWBaseDirectory").ToString() +
  11:                    "\\wwwroot\\cars.json";
  12:              var json = System.IO.File.ReadAllText(pfad);
  13:                 CarListe = JsonSerializer.Deserialize<Car[]>(json, options).ToList(); //Parse 
  14:      }
  15:  }

Der Pfad aus Zeile 10 im vorigen Listing wird in der Startup.cs gefüllt und steht so Anwendungsweit zur Verfügung. Dies würde ich als C# Code bezeichnen, der sich in jedem dotnet core Projekt finden wird.

   1:  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
   2:   {
   3:    AppDomain.CurrentDomain.SetData("WWWBaseDirectory", env.ContentRootPath);

In der gleichen Datei wird der CarService dem Dependency Injection Container hinzugefügt.

   1:  public void ConfigureServices(IServiceCollection services)
   2:   {
   3:    services.AddRazorPages();
   4:    services.AddSingleton<CarService>();
   5:   }

Fügen Sie nun im Pages Ordner eine Razor Page hinzu, die letztendlich das Input Element beinhalten wird und nennen Sie diese lookup.cshtml.

image

Um am Ende einen Ajax Call Back zu beantworten wird eine Page Method mit JSON Rückgabe erstellt. Man findet diesen Anwendungsfall häufig mit einem Partial als Rückgabe. Aber es gibt auch Json als Result. Per DI wird der CarService injiziert. So kann man dann im C# Code in Zeile 3 eine LINQ Query absetzen, mit dem Ziel die Autocomplete Box Vorschlagsliste mit passenden Einträgen zu füllen. Damit diese nicht zu lange wird, per Take auf 10 Elemente begrenzt. Der 2te Parameter und praktisch echte Parameter wir per Binding aus dem Querystring automatisch gefüllt.

   1:  public JsonResult OnGetList([FromServices] CarService _carService,string suche)
   2:    {
   3:       var q = _carService.CarListe.Where(x => x.name.ToLower().Contains(suche.ToLower())).Take(10);
   4:       var ret = new List<autocomplete>();
   5:       foreach (var item in q)
   6:        {
   7:         ret.Add(new autocomplete { data = item.name, value = item.name });
   8:        }
   9:       return new JsonResult(ret);
  10:   }

Die genutzte autocomplete JavaScript Bibliothek erfordert die Rückgabe in einem speziellen Json Format, weshalb hier noch eine c# Helper autocomplete Klasse erstellt wird.

   1:  public class autocomplete
   2:  {
   3:      public string value { get; set; }
   4:      public string data { get; set; }
   5:    }

Letztendlich wird der HTML Razor View editiert. Ein HTML Input Element dient als Testfall für autocomplete. Das Handler Attribut in @page routed Browser Aufrufe an lookup/List am Server in die Page Handler Methode OnGetList.

   1:  @page "{handler?}"
   2:  @model WebApplication1.Pages.lookupModel
   3:  <input id="auto" />

 

Am Ende der lookup.cshtml wird der JavaScript Code eingefügt, der aus der normalen Textbox eine Autocomplete Textbox macht. Der Ajax Callback mit dem Data Suchewert wird übersetzt in Lookup/list?suche=a

   1:  @section Scripts
   2:  {
   3:      <script>
   4:          $('#auto').autocomplete({
   5:              lookup: function (query, done) {
   6:                 
   7:                  $.ajax({
   8:                      type: "GET",
   9:                      url: "Lookup/List",
  10:                      data: { 'suche': query },
  11:                      contentType: "application/json; charset=utf-8",
  12:                      dataType: "json",
  13:                      success: function (data) {
  14:                          var result = new Object();
  15:                          result.suggestions = data;
  16:                          done(result);
  17:                      },
  18:                      failure: function (response) {
  19:                          alert(response);
  20:                      }
  21:                  });
  22:              },
  23:              onSelect: function (suggestion) {
  24:                  $('#auto').val(suggestion.data);
  25:              }
  26:          });
  27:          //fix für touch und Maus
  28:          $(document).on('mousedown', '.autocomplete-suggestion', e => {
  29:    $(e.target).click();
  30:  });
  31:   
  32:      </script>
Kommentare sind geschlossen