Teil 5: Erstellen einer dynamischen Benutzeroberfläche mit Knockout.js
von Rick Anderson
Abgeschlossenes Projekt herunterladen
Erstellen einer dynamischen Benutzeroberfläche mit Knockout.js
In diesem Abschnitt verwenden wir Knockout.js, um der ansicht Admin Funktionen hinzuzufügen.
Knockout.js ist eine Javascript-Bibliothek, die das Binden von HTML-Steuerelementen an Daten erleichtert. Knockout.js verwendet das MVVM-Muster (Model-View-ViewModel).
- Das Modell ist die serverseitige Darstellung der Daten im Geschäftsbereich (in unserem Fall Produkte und Bestellungen).
- Die Ansicht ist die Präsentationsebene (HTML).
- Das View-Model ist ein Javascript-Objekt , das die Modelldaten enthält. Das Ansichtsmodell ist eine Code-Abstraktion der Benutzeroberfläche. Sie hat keine Kenntnisse über die HTML-Darstellung. Stattdessen stellt sie abstrakte Features der Ansicht dar, z. B. "eine Liste von Elementen".
Die Ansicht ist an das Ansichtsmodell datengebunden. Updates zum Ansichtsmodell werden automatisch in der Ansicht widergespiegelt. Das Ansichtsmodell ruft auch Ereignisse aus der Ansicht ab, z. B. Schaltflächenklicks, und führt Vorgänge für das Modell aus, z. B. das Erstellen einer Bestellung.
Diagramm, das die Interaktion zwischen H T M L-Daten, dem Ansichtsmodell, j son und dem Web-AP I-Controller zeigt. Das Datenfeld "H T M L" ist mit "Ansicht" gekennzeichnet. Ein doppelter Pfeil mit der Bezeichnung Datenbindung verknüpft das Datenfeld "H T M L" mit dem Feld "Ansichtsmodell". Ein Doppelpfeil mit der Bezeichnung H T T P-Anforderungen und j son-Modell vom Server verknüpft das Ansichtsmodell mit dem Web-AP I-Controller.
Zunächst definieren wir das Ansichtsmodell. Danach binden wir das HTML-Markup an das Ansichtsmodell.
Fügen Sie den folgenden Razor-Abschnitt zu Admin.cshtml hinzu:
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.1.0.js")"></script>
<script type="text/javascript">
// View-model will go here
</script>
}
Sie können diesen Abschnitt an einer beliebigen Stelle in der Datei hinzufügen. Wenn die Ansicht gerendert wird, wird der Abschnitt unten auf der HTML-Seite direkt vor dem schließenden <Tag /body> angezeigt.
Das gesamte Skript für diese Seite befindet sich innerhalb des skripttags, das durch den Kommentar angegeben wird:
<script type="text/javascript">
// View-model will go here
</script>
Definieren Sie zunächst eine View-Model-Klasse:
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
}
ko.observableArray ist eine besondere Art von Objekt in Knockout, das als beobachtbar bezeichnet wird. Aus der Knockout.js Dokumentation: Ein beobachtbares objekt ist ein "JavaScript-Objekt, das Abonnenten über Änderungen benachrichtigen kann". Wenn sich der Inhalt einer beobachtbaren Änderung ändert, wird die Ansicht automatisch entsprechend aktualisiert.
Um das Array aufzufüllen products
, stellen Sie eine AJAX-Anforderung an die Web-API. Denken Sie daran, dass wir den Basis-URI für die API im Ansichtsbehälter gespeichert haben (siehe Teil 4 des Tutorials).
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
// New code
var baseUri = '@ViewBag.ApiUrl';
$.getJSON(baseUri, self.products);
}
Als Nächstes fügen Sie dem Ansichtsmodell Funktionen hinzu, um Produkte zu erstellen, zu aktualisieren und zu löschen. Diese Funktionen übermitteln AJAX-Aufrufe an die Web-API und verwenden die Ergebnisse, um das Ansichtsmodell zu aktualisieren.
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
var baseUri = '@ViewBag.ApiUrl';
// New code
self.create = function (formElement) {
// If the form data is valid, post the serialized form data to the web API.
$(formElement).validate();
if ($(formElement).valid()) {
$.post(baseUri, $(formElement).serialize(), null, "json")
.done(function (o) {
// Add the new product to the view-model.
self.products.push(o);
});
}
}
self.update = function (product) {
$.ajax({ type: "PUT", url: baseUri + '/' + product.Id, data: product });
}
self.remove = function (product) {
// First remove from the server, then from the view-model.
$.ajax({ type: "DELETE", url: baseUri + '/' + product.Id })
.done(function () { self.products.remove(product); });
}
$.getJSON(baseUri, self.products);
}
Der wichtigste Teil: Wenn das DOM geladen ist, rufen Sie die ko.applyBindings-Funktion auf, und übergeben Sie eine neue instance von ProductsViewModel
:
$(document).ready(function () {
ko.applyBindings(new ProductsViewModel());
})
Die ko.applyBindings-Methode aktiviert Knockout und verbindet das View-Modell mit der Ansicht.
Nachdem wir nun über ein Ansichtsmodell verfügen, können wir die Bindungen erstellen. In Knockout.js fügen Sie dazu HTML-Elementen Attribute hinzu data-bind
. Um beispielsweise eine HTML-Liste an ein Array zu binden, verwenden Sie die foreach
Bindung:
<ul id="update-products" data-bind="foreach: products">
Die foreach
Bindung durchläuft das Array und erstellt untergeordnete Elemente für jedes Objekt im Array. Bindungen für die untergeordneten Elemente können auf Eigenschaften der Arrayobjekte verweisen.
Fügen Sie der Liste "update-products" die folgenden Bindungen hinzu:
<ul id="update-products" data-bind="foreach: products">
<li>
<div>
<div class="item">Product ID</div> <span data-bind="text: $data.Id"></span>
</div>
<div>
<div class="item">Name</div>
<input type="text" data-bind="value: $data.Name"/>
</div>
<div>
<div class="item">Price ($)</div>
<input type="text" data-bind="value: $data.Price"/>
</div>
<div>
<div class="item">Actual Cost ($)</div>
<input type="text" data-bind="value: $data.ActualCost"/>
</div>
<div>
<input type="button" value="Update" data-bind="click: $root.update"/>
<input type="button" value="Delete Item" data-bind="click: $root.remove"/>
</div>
</li>
</ul>
Das <li>
-Element tritt innerhalb des Bereichs der foreach-Bindung auf. Das bedeutet, dass Knockout das Element für jedes Produkt im products
Array einmal rendert. Alle Bindungen innerhalb des <li>
Elements beziehen sich auf dieses Produkt instance. Bezieht sich beispielsweise $data.Name
auf die Name
-Eigenschaft des Produkts.
Verwenden value
Sie die Bindung, um die Werte der Texteingaben festzulegen. Die Schaltflächen sind mithilfe der Bindung an Funktionen in der click
Modellansicht gebunden. Das Produkt instance wird als Parameter an jede Funktion übergeben. Weitere Informationen finden Sie in der Knockout.js Dokumentation zu den verschiedenen Bindungen.
Fügen Sie als Nächstes eine Bindung für das Submit-Ereignis auf dem Formular Produkt hinzufügen hinzu:
<form id="addProduct" data-bind="submit: create">
Diese Bindung ruft die create
Funktion für das Ansichtsmodell auf, um ein neues Produkt zu erstellen.
Hier sehen Sie den vollständigen Code für die ansicht Admin:
@model ProductStore.Models.Product
@{
ViewBag.Title = "Admin";
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.0.0.js")"></script>
<script type="text/javascript">
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
var baseUri = '@ViewBag.ApiUrl';
self.create = function (formElement) {
// If valid, post the serialized form data to the web api
$(formElement).validate();
if ($(formElement).valid()) {
$.post(baseUri, $(formElement).serialize(), null, "json")
.done(function (o) { self.products.push(o); });
}
}
self.update = function (product) {
$.ajax({ type: "PUT", url: baseUri + '/' + product.Id, data: product });
}
self.remove = function (product) {
// First remove from the server, then from the UI
$.ajax({ type: "DELETE", url: baseUri + '/' + product.Id })
.done(function () { self.products.remove(product); });
}
$.getJSON(baseUri, self.products);
}
$(document).ready(function () {
ko.applyBindings(new ProductsViewModel());
})
</script>
}
<h2>Admin</h2>
<div class="content">
<div class="float-left">
<ul id="update-products" data-bind="foreach: products">
<li>
<div>
<div class="item">Product ID</div> <span data-bind="text: $data.Id"></span>
</div>
<div>
<div class="item">Name</div>
<input type="text" data-bind="value: $data.Name"/>
</div>
<div>
<div class="item">Price ($)</div>
<input type="text" data-bind="value: $data.Price"/>
</div>
<div>
<div class="item">Actual Cost ($)</div>
<input type="text" data-bind="value: $data.ActualCost"/>
</div>
<div>
<input type="button" value="Update" data-bind="click: $root.update"/>
<input type="button" value="Delete Item" data-bind="click: $root.remove"/>
</div>
</li>
</ul>
</div>
<div class="float-right">
<h2>Add New Product</h2>
<form id="addProduct" data-bind="submit: create">
@Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
@Html.EditorForModel()
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
</div>
</div>
Führen Sie die Anwendung aus, melden Sie sich mit dem Administratorkonto an, und klicken Sie auf den Link "Admin". Die Liste der Produkte sollte angezeigt werden, und Sie sollten in der Lage sein, Produkte zu erstellen, zu aktualisieren oder zu löschen.