2016-07-22 12 views
0

Für eine Zeiterfassungs Anwendung ich eine beobachtbare Array:beobachtbare Array Wert Stand

DayHrs

DayHrs entweder 5 oder 7 Tage enthalten auf den Mitarbeitern abhängig. Ich habe eine gesamte WeekHrs, die ein berechnetes Feld ist.

Wenn ein Benutzer einen Wert für einen der DayHrs eingibt, möchte ich das gesamte WeekHrs-Feld sofort aktualisieren.

Also in meiner Datenbindung möchte ich ValueUpdate verwenden: 'afterkeydown'.

Allerdings kann ich dies nicht zu einem berechneten Feld machen, da die Array-Elemente im beobachtbaren Array selbst nicht beobachtbar sind.

Gemäß der Knockout-Dokumentation: Schlüsselpunkt: Ein ObservableArray verfolgt, welche Objekte sich im Array befinden, nicht den Status dieser Objekte.

Also, wie behebe ich das? Gibt es eine Möglichkeit, das Array zu durchlaufen, um jedes Objekt beobachtbar zu machen (ich habe nicht gesehen, wie das geht) oder soll ich ein Änderungsereignis angeben? Oder etwas anderes?

Antwort

2

Es gibt zwei Möglichkeiten der Umwandlung von „plain JavaScript-Objekte“ in Viewmodel mit beobachtbaren Eigenschaften:

  1. automatisch über ko.mapping.fromJS oder
  2. manuell.

Ich werde eine Antwort geben, wenn Sie mit der Option 2. hinwollen Wenn Sie es automatisch tun wollen (1), ist es wahrscheinlich am besten einen Blick in die Dokumentation haben und Beispiele here.

Im folgenden Code habe ich ein Beispiel geschrieben, das einfache JavaScript-Objekte und -Arrays in ko.observable und ko.observableArray Eigenschaften konvertiert. Jedes Viewmodel hat einen Konstruktor oder eine statische create Methode, die weiß, wie man mit einem bestimmten Datenformat umgeht. Für jede Eigenschaft in Ihren Daten können Sie wählen, entweder:

  1. es ignorieren (es hat keinen Zweck in Ihrem Viewmodel nicht dienen, wenn es nicht in einer Ansicht gerendert wird)
  2. Machen Sie ihm eine regelmäßige Eigenschaft (wenn es statisch in Ihrer Ansicht gerendert)
  3. machen Sie es zu beobachten (wenn es in der Ansicht aktualisiert werden muss)

Dann können Sie ko.computed Eigenschaften und Methoden hinzufügen zu Ihrer Ansicht interaktiv zu machen.

var Day = function(initialHours) { 
 
    this.hours = ko.observable(initialHours || 0); 
 
}; 
 

 
Day.create = function(data) { 
 
    return new Day(data.Hours); 
 
} 
 

 
var Week = function(initialDays) { 
 
    this.days = ko.observableArray(initialDays.map(Day.create)); 
 
    
 
    this.totalHours = ko.pureComputed(function() { 
 
    return this.days().reduce(function(sum, day) { 
 
     return sum + parseInt(day.hours(), 10); 
 
    }, 0); 
 
    }, this); 
 
}; 
 
    
 
Week.create = function(dayArray) { 
 
    return new Week(dayArray); 
 
}; 
 

 
var Employee = function(employeeData) { 
 
    this.name = employeeData.Name; 
 
    this.workWeek = Week.create(employeeData.WorkWeek); 
 
}; 
 

 
Employee.create = function(employeeData) { 
 
    return new Employee(employeeData); 
 
}; 
 

 
var testData = [{ 
 
    Name: "John Doe", 
 
    WorkWeek: [ 
 
    { Hours: 4 }, 
 
    { Hours: 8 }, 
 
    { Hours: 8 }, 
 
    { Hours: 8 }, 
 
    { Hours: 6 } 
 
    ] 
 
}]; 
 
    
 
var vm = { 
 
    employees: testData.map(Employee.create) 
 
}; 
 

 
ko.applyBindings(vm);
input[type="number"] { width: 30px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 

 

 
<ul data-bind="foreach: employees"> 
 
    <li> 
 
    <div data-bind="text: name"></div> 
 
    <div data-bind="with: workWeek"> 
 
     <!-- ko foreach: days --> 
 
     <input data-bind="value: hours" type="number"/> - 
 
     <!-- /ko --> 
 
     <span data-bind="text: 'total: ' + totalHours()"></span> 
 
    </div> 
 
    </li> 
 
</ul>