KnockoutJS: Hinzufügen von Observable-Eigenschaften und -Funktionen zu Objekten in einem von ObservableArray generierten Mapping
-
28-10-2019 - |
Frage
Ich bin neu in KnockoutJS und versuche nicht, den generierten Objekten zusätzliche Eigenschaften und Methoden hinzuzufügen im ko.observableArray()
, wie er vom mapping
-Plugin erstellt wurde.
Hier bin ich:
- Ich habe ein JSON-Array mit
Users
- Ich habe den
ko.observableArray()
mit dem Mapping-Plugin erstellt - Ich habe eine Vorlage, die Tabellenzeilen für jeden
User
erstellt, soweit so gut: o)
Folgendes versuche ich zu tun:Jeder
User
hat eine Eigenschaft namens'IsActive'
- Ich möchte ein Klickereignis auf eine Methode für jedesdata-bind
-Objekt generieren, das dieseUser
-Eigenschaft umschaltet.Diese Frage sah vielversprechend aus , scheint mir jedoch eine unnötige Vervielfältigung zu sein das gesamte Ansichtsmodell in JS deklarieren zu müssen (es sei denn, ich muss es so machen!) - ist es möglich, nur das generierte Objekt zu erweitern?
Hier ist der Code: http://jsfiddle.net/yZkSf/2/ (funktioniert noch nicht in JS Fiddle - aber ich werde weiter damit spielen und diesen Link aktualisieren, wenn es funktioniert).
Lösung
Es gibt verschiedene Optionen, die Sie in Betracht ziehen könnten.
-Eine ist die Verwendung des create
callback , um zu steuern, wie Ihr "Benutzer" "Objekte werden erstellt. Sie können die Observablen entweder selbst definieren und zusätzliche Funktionen hinzufügen oder das Mapping-Plugin für das einzelne Benutzerobjekt aufrufen und dann zusätzliche Funktionen hinzufügen.
Wäre ungefähr so: http://jsfiddle.net/rniemeyer/fkVaK/
- Andernfalls können Sie die Funktion "Umschalten" in Ihr viewModel einfügen und dann das Objekt "Benutzer" an dieses übergeben.
Eine gute Möglichkeit mit 1.3 ist die Verwendung von ko.dataFor
zusammen mit der Live- / Delegate- / On-Event-Delegierungsfunktion von jQuery. Wäre wie folgt: http://jsfiddle.net/rniemeyer/FkjNr/
//unobtrusive event handler
$(".toggle").live("click", function() {
var user = ko.dataFor(this);
if (user) {
viewModel.toggleIsActive(user);
}
});
Wenn Sie die Ereignisdelegierung nicht verwenden möchten, können Sie das Element direkt mit einer anonymen Funktion wie der folgenden übergeben: > http://jsfiddle.net/rniemeyer/GpQtN/
BEARBEITEN: Ab Version 2.0 werden die aktuellen Daten automatisch an den Handler übergeben, wenn Klick- / Ereignisbindungen verwendet werden. Sie können also einfach Folgendes tun:
<a href="#" data-bind="click: $root.toggleIsActive"><span data-bind="text: IsActive"></span></a>
Andere Tipps
Dies ist, was ich mit Ihren und Ryans Antworten gefunden habe ... scheint zu funktionieren.Bitte hinterlassen Sie Feedback, da ich neu bei Knockout bin und selbst neugierig bin, ob dies ein guter Ansatz ist.
JS:
$(function() {
$.get("users/getUsers", function(r){
var vm = ko.mapping.fromJS(r, {
users: {
create: function(user){
var methods = {
toggleIsActive: function(u){u.IsActive(!u.IsActive());},
foo: function(u){console.log(u);},
bar: function(u){/*whatever*/},
}
return $.extend(ko.mapping.fromJS(user.data), methods);
}
}
});
ko.applyBindings(vm);
}, 'json');
});
$(function() {
$.get("users/getUsers", function(r){
var vm = ko.mapping.fromJS(r, {
users: {
create: function(user){
var methods = {
toggleIsActive: function(u){u.IsActive(!u.IsActive());},
foo: function(u){console.log(u);},
bar: function(u){/*whatever*/},
}
return $.extend(ko.mapping.fromJS(user.data), methods);
}
}
});
ko.applyBindings(vm);
}, 'json');
});
DOM:
<!-- ko foreach: users -->
<a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->
<!-- ko foreach: users -->
<a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->
Ich habe einen Weg gefunden, dies zu tun, aber es bedeutet, die generierten Objekte im Array zu durchlaufen, sobald sie erstellt wurden. Ich würde es vorziehen, das gleiche Ergebnis ohne die zusätzliche Schleife zu erzielen.
BEARBEITEN: Wie RP Niemeyer in seiner Antwort vorschlägt! ; o)
Eine Möglichkeit, einem vorhandenen Objekt Eigenschaften hinzuzufügen, ist die Verwendung von jQuery verlängern () um die Objekte zu kombinieren.
Deklarieren Sie zunächst die zusätzlichen Eigenschaften und Funktionen in einem neuen Objekt:
var userModel = {
toggleIsActive: function() {
console.log('toggleIsActive called: before: ' + this.IsActive());
this.IsActive(!this.IsActive());
// todo: save!
console.log('toggleIsActive called: after: ' + this.IsActive());
}
}
Führen Sie dann nach dem Aufruf des ko.mapping.fromJS()
, jedoch vor dem Aufruf des ko.applyBindings()
eine Schleife durch die Objekte im generierten Array und erweitern Sie sie:
viewModel.users = ko.mapping.fromJSON(/* get JSON */);
for (var i = 0; i < viewModel.users().length; i++) {
$.extend(viewModel.users()[i], userModel);
}
ko.applyBindings(viewModel);