Ein Auswahlfeld wird oft für die Festlegung einer "belongs_to"-Verknüpfung verwendet, aber Sie sollten auch in Betracht ziehen, ein Textfeld mit automatischer Vervollständigung zu verwenden. Hier verwende ich jQuery UI und zeige zwei verschiedene Lösungen: eine auf der Clientseite und eine auf der Serverseite.
Ein Produkt zu dieser App hinzuzufügen
Sagen Sie, wir haben eine einfache Anwendung, die eine Anzahl von Produkten verwaltet, von denen jedes zu einer Kategorie gehört. Um ein Produkt zu dieser App hinzuzufügen, haben wir ein Formular, das unten angezeigt wird, und das eine Dropdown-Liste für die Auswahl der Kategorie des neuen Produkts enthält.
$ rails g scaffold Product name price category:references
$ rails g scaffold Category name
$ rails db:migrate
Dieser Ansatz funktioniert gut für eine begrenzte Anzahl von Kategorien, aber Dropdown-Listen können schnell umständlich werden, wenn es eine große Anzahl von Optionen zur Auswahl gibt. In dieser Episode werden wir dieses Dropdown durch ein Textfeld ersetzen, das automatisch vervollständigt wird, wenn ein Benutzer den Namen einer Kategorie eingibt.
Die Vorlage, die das Formular rendert, wird unten gezeigt. Sie verwendet "collection_select", um das Dropdown für die Kategorie-Verknüpfung zu erstellen.
Wenn wir versuchen, das Formular jetzt neu zu laden, sehen wir eine Fehlermeldung, da das Produktmodell kein Attribut "category_name" hat. Um dies zu beheben, werden wir ein virtuelles Attribut erstellen.
// app/controllers/products_controller.rb
defproduct_params
params.require(:product).permit(:name, :price, :category_name)
end
Wir haben Getter- und Setter-Methoden für "category_name" erstellt. Der Getter gibt den Namen der zugehörigen Kategorie zurück (aber beachten Sie, dass wir "try" verwenden, damit es "nil" zurückgibt, wenn keine zugehörige Kategorie vorhanden ist). Der Setter setzt die Kategorie des Produkts auf die Kategorie mit dem übereinstimmenden Namen, wenn der Name vorhanden ist. 2.png620 KB
Wenn wir das Formular jetzt neu laden, haben wir ein Feld für den Kategorienamen. Wenn wir ein Produkt mit einem bereits vorhandenen Kategorienamen hinzufügen, wird das Produkt zur Datenbank hinzugefügt und die Zuordnung zu seiner Kategorie wird festgelegt. 3.png614 KB
Was sollte jedoch passieren, wenn jemand ein Produkt mit einer neuen Kategorie erstellt? Es wäre gut, wenn die neue Kategorie in solchen Fällen zusammen mit dem Produkt erstellt würde, und Rails macht dies einfach möglich. Alles, was wir tun müssen, ist, find_by_name im Setter durch find_or_create_by zu ersetzen.
// app/model/product.rb
defcategory_name=(name)
self.category = Category.find_or_create_by(name:) if name.present?
end
Jetzt, wenn wir ein Produkt mit einer neuen Kategorie hinzufügen, wird die Kategorie ebenfalls erstellt.
Adding Auto-completion
Was wir wirklich tun möchten, ist die Autovervollständigung hinzufügen, damit während der Eingabe in das Kategorienfeld die Kategorien, die dem Eingegebenen entsprechen, angezeigt werden. Eine der einfachsten Möglichkeiten, dies in einer Rails 3.1-Anwendung zu tun, besteht darin, jQuery UI zu verwenden, das über ein Autocomplete-Widget verfügt. Daher werden wir diesen Ansatz verfolgen.
In diesem Code überprüfen wir zunächst, ob der DOM geladen wurde. Wenn dies der Fall ist, suchen wir unser Kategorienamen-Feld anhand seiner ID und rufen die Autocomplete-Funktion auf. Diese Funktion nimmt eine Option namens "source" entgegen, die bestimmt, woher die Autocomplete-Optionen stammen. Wir können ihr entweder eine URL übergeben, was eine AJAX-Anfrage auslöst und das zurückgegebene Ergebnis verwendet, oder ein Array von Optionen. Um die Dinge schnell zum Laufen zu bringen, haben wir vorerst ein Array verwendet.
Wenn wir nun zur Seite für das Hinzufügen eines neuen Produkts gehen und etwas eingeben, das mit einem oder mehreren Elementen im Array übereinstimmt, sehen wir die Autocomplete-Liste. 4.png634 KB
Die Autocomplete-Liste funktioniert, aber sie sieht schrecklich aus. Wir werden dies verbessern, indem wir den folgenden Code zur SCSS-Datei der Produkte hinzufügen.
Wenn wir die Seite jetzt neu laden, sieht die Liste viel besser aus. 5.png621 KB
Autocomplete-Werte aus der Datenbank abrufen
Nun, da unsere Liste gut aussieht, können wir uns darauf konzentrieren, sie mit den übereinstimmenden Kategorien aus der Datenbank zu füllen, anstelle der Werte aus dem Array. Es gibt zwei Möglichkeiten, dies zu tun, und wir werden Ihnen beide Ansätze hier zeigen.
Die erste Option behält alles auf dem Client bei. Dies funktioniert gut, wenn es nicht viele Optionen zur Auswahl gibt, wie es hier der Fall ist. Was wir tun, ist, alle Optionen in einem Datenattribut auf dem Textfeld für den Kategorienamen einzubetten.
Um dies zu tun, setzen wir eine Datenoption auf das Textfeld (dieser Daten-Hash ist neu in Rails 3.1 und bietet eine bequeme Möglichkeit, Datenattribute zu setzen) und übergeben ihm ein Array von Kategorienamen. Wenn wir die Seite neu laden und den Quellcode anzeigen, sehen wir, was dies bewirkt hat.
Das Textfeld hat jetzt ein Datenattribut data-autocomplete-source, das die Kategorien enthält. Diese wurden in einen JSON-String umgewandelt und HTML-escaped. Jetzt können wir die Dummy-Daten in der Autocomplete-Funktion durch die Daten aus diesem Attribut ersetzen.
Wenn wir die Seite jetzt neu laden und Text im Feld für den Kategorienamen eingeben, erscheinen die passenden Kategorien in der Autocomplete-Liste. 6.png618 KB
Dies ist alles, was wir tun müssen, um die Autocomplete-Funktion auf dem Client zum Laufen zu bringen, und dieser Ansatz funktioniert perfekt für uns, da wir nur eine begrenzte Anzahl von Kategorien haben. Es gibt jedoch andere Situationen, in denen wir Hunderte oder sogar Tausende von potenziellen Optionen haben könnten, und es wäre unpraktisch, jede Option auf dem Client zu haben. In solchen Fällen ist es besser, anstelle sie in das HTML-Dokument einzubetten, eine AJAX-Anfrage zu verwenden, um die Autocomplete-Optionen vom Server abzurufen.
Um dies zu tun, übergeben wir der Autocomplete-Funktion anstelle eines Arrays eine URL. Wir werden die Daten im Attribut data-autocomplete-source durch eine URL ersetzen. Da die AJAX-Anfrage eine Liste von Kategorien zurückgeben sollte, verwenden wir die URL categories_path.
Jetzt werden wir in unserem neuen CategoriesController die Index-Action schreiben. Diese wird die Kategorien abrufen, die mit dem, was in das Textfeld eingegeben wurde, übereinstimmen, und sie als JSON-Daten zurückgeben.
// app/controllers/categories_controller.rbclass CategoriesController < ApplicationController
before_action :set_category, only: %i[show edit update destroy]
# GET /categories or /categories.json
def index
#@categories = Category.all
@categories = Category.order(:name).where('name like ?', "#{params[:term]}%")
render json: @categories.map(&:name)
end
Das Autocomplete-Widget gibt den Text aus dem Textfeld als term-Parameter weiter, den wir dann verwenden, um die Kategorien zu filtern. Wir geben diese gefilterte Liste als Array von Namen zurück.
Wenn wir die Seite neu laden und nun im Kategorienamen-Feld zu tippen beginnen, werden die übereinstimmenden Kategorien vom Server abgerufen.
7.png602 KB
Die Autocomplete-Liste ist etwas langsamer, da bei jeder Änderung des Texts im Textfeld eine AJAX-Anfrage gestellt wird. Allerdings müssen wir die vollständige Liste der Kategorien nicht mehr bei jedem Laden der Seite an den Client senden.
Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten
zu können und die Zugriffe auf unsere Website zu analysieren.
Sie akzeptieren unsere Cookies, wenn Sie fortfahren diese Webseite zu nutzen.
Datenschutzerklärung.