2016-04-18 5 views
-1

Was ich versuche zu tun ist, um Daten vom Server und dann alles in eine beobachtbare setzen und dann alle Eigenschaften beobachtbar machen. Das Problem, mit dem ich konfrontiert bin, ist, dass es nicht alle meine Eigenschaften beobachtbar macht und ich brauche sie alle, um beobachtbar zu sein, da manchmal abhängig von den Daten einige Eigenschaften beobachtbar sind und manchmal nicht.Knockout JS nicht setzen alle Mitglieder beobachtbar

var viewModel = this; 
viewModel.Model = ko.observable(); 

viewModel.SetModel = function (data) { 
viewModel.Model(ko.mapping.fromJS(data)); 
} 

Die Daten, die vom Server I empfangen ist wie das zum Beispiel: normaldata, Artikel (das ein Array mit unbekannter Anzahl von Elementen ist). also wenn ich versuche, auf Daten wie viewModel.Model().Items[0]().Layer() zuzugreifen, habe ich manchmal Schicht als Funktion und manchmal ist es ein normales Element mit beobachtbaren Elementen. Ich will alle meine Gegenstände innerhalb der Einzelteile, um Schicht als Funktion zu haben.

Server-Daten Beispiel: Name: "test" Artikel: [Schicht [ID: 132]] In diesem Beispiel Namen, Artikel und ID beobachtbar ist aber Schicht nicht.

Fiddle Beispiel: jsfiddle.net/98dv11yz/3 Also das Problem ist, dass manchmal die Schicht null ist, was zu ko macht die Eigenschaft zu beobachten, aber manchmal die Eigenschaft hat id und ko macht nur die untergeordneten Elemente beobachtet werden. Das Problem ist, dass ich habe, wenn es im Code ist und ich möchte, dass es eine Funktion ist, so kann ich es immer als Schicht() sagen, denn jetzt ist es manchmal Schicht oder Schicht()

+0

Der Beitrag ist ziemlich schwer zu verstehen. Bitte lesen Sie es erneut und versuchen Sie es zu klären, und versuchen Sie, eine [mcve] einzubeziehen. – Jeroen

+0

bearbeitet ... hoffe das ist gut genug! – xDevil

+0

Sorry, es hilft mir nicht allzu sehr, fürchte ich. Hast du den Link von meinem vorherigen Kommentar überprüft? Versuchen Sie, eine * runnable * (aber minimale) Repro für Ihre Situation zu erstellen. Von dem, was du bisher gepostet hast, scheint das vollkommen möglich zu sein. (Darüber hinaus hilft es auch, wenn Sie auf die Formatierung und wenn möglich Rechtschreibung in Ihrem Beitrag achten; es gibt eine Live-Vorschau beim Bearbeiten.) – Jeroen

Antwort

3

Eine Erläuterung für was passiert:

Wenn das Plugin ko.mapping auf ein Objekt in Ihrer Eingabe trifft, werden die Eigenschaften des Objekts beobachtbar, nicht die Eigenschaft selbst.

Zum Beispiel:

var myVM = ko.mapping.fromJS({ 
    name: "Foo", 
    myObject: { 
    bar: "Baz" 
    } 
}); 

Wird einkochen zu:

var myVM = { 
    name: ko.observable("Foo"), 
    myObject: { 
    bar: ko.observable("Baz") 
    } 
} 

und nicht zu:

var myVM = { 
    name: ko.observable("Foo"), 
    myObject: ko.observable({ 
    bar: ko.observable("Baz") 
    }) 
} 

Das Problem mit der Struktur Ihrer Daten ist, dass myObject wird manchmal sei null und manchmal ein Objekt sein. Die erste wird genauso behandelt wie die Eigenschaft name in diesem Beispiel, die letztere wird als myObject prop behandelt.

Mein Vorschlag:

Erstens: Ich würde vorschlagen, nur die ko.mapping.fromJS Methode verwenden, wenn Sie eine gut dokumentierte und einheitliche Datenstruktur haben und nicht auf große Datenmengen, die viele Ebene und Komplexität haben . Manchmal ist es einfacher, schlanke Ansichtsmodelle zu erstellen, die in ihrem Konstruktor über eine eigene Zuordnungslogik verfügen.

Wenn Sie Ihre Datenstruktur nicht ändern möchten und ko.mapping mit behalten möchten, wird dieser Teil haben geändert Client-Seite sein:

Items: [ 
    { layer: {id: "0.2"} }, 
    { layer: null} 
] 

Sie müssen werde entscheiden, was Sie erreichen wollen . Sollte das Viewmodel den Artikel mit einer null Schicht ausziehen?Oder willst du es rendern und aktualisieren können? Hier ist ein Beispiel dafür, wie man „korrigieren“, um Ihre Daten vor einem View-Modell zu erstellen:

var serverData = { 
    Name: "Example Name", 
    Id: "0", 
    Items: [ 
    {layer: {id: "0.2"} }, 
    {layer: null} 
    ] 
}; 

var correctedData = (function() { 
    var copy = JSON.parse(JSON.stringify(serverData)); 

    // If you want to be able to render the null item: 
    copy.Items = copy.Items.map(function(item) { 
    return item.layer ? item : { layer: { id: "unknown" } }; 
    }); 

    // If you don't want it in there: 
    copy.Items = copy.Items.filter(function(item) { 
    return item.layer; 
    }); 

    return copy; 
}()); 

Ob diese Lösung akzeptabel Art beruht, wie viel komplizierter Ihr realer Einsatz sein wird. Wenn die Daten komplexer und interaktiver sind, würde ich vorschlagen, die Elemente ihren eigenen Ansichtsmodellen zuzuordnen, die sich mit fehlenden Eigenschaften beschäftigen und was nicht ...

+0

danke! das ist was ich gesucht habe! – xDevil