2017-04-25 5 views
0

Ich habe viele (KnockOut) Ansicht Modelle, die Daten von einem Rest-Service erhalten und dann "Element" Ansicht Modelle, die ziemlich einfach sind und nur die Felder aus der REST-Schnittstelle enthalten.Dynamic Item ViewModel Knockout

Ich habe mich nur gefragt, ob es eine Möglichkeit gab, die Item-Viewmodels nicht zu definieren, sondern sie nur dynamisch als Objekte zu erstellen (wobei jede Eigenschaft beobachtbar ist).

Also im folgenden Beispiel möchte ich nicht das "ItemViewModel" haben, sondern einfach innerhalb der AddItems-Funktion sagen, dass es ein Objekt basierend auf den Daten erstellen und jeden Eintrag ko.observable machen soll. Der übergebene "itemName" enthält dann "ItemViewModel1" (oder in einem anderen Aufruf "ItemViewModel2" ... etc).

Also z.B. wenn die Json Ruhe Eingang ein Feld „LAST_NAME“ hat, würde es hinzufügen self.LAST_NAME = ko.observable()“mit diesem Wert gefüllt usw. (so kann ich es immer noch in den Ansichten verweisen).

var ItemViewModel1 = function (data) { 
    var self = this; 
    self.PAR1 = ko.observable(data.PAR1) 
    self.PAR2 = ko.observable(data.PAR2) 
    self.PAR3 = ko.observable(data.PAR3) 
    self.PAR4 = ko.observable(data.PAR4) 
    // … etc 
} 
var MasterViewModel1 = function (data) { 
    var self = this; 
    ReportBaseViewModel.call(self) 
} 

var ReportBaseViewModel = function() { 
    var self = this; 

    /* commonly used vars */ 
    self.report = ko.observable(); 
    self.searchedCallBackFunction = ko.observable(); 
    self.items = ko.observableArray(); 
    self.selecteditem = ko.observable(); 
    self.selectedPerson = ko.observable(); 

    /* method: print */ 
    self.PrintEventHandler = function (data) { window.print(); }; 

    /* method: add items to array */ 
    self.AddItems = function (data) { 
     var newitems = ko.utils.arrayMap(data, function (item) { 
      c = new window[self.itemname](item); 
      return c; 
     }); 
     self.items(newitems); 
    }; 

    /* eventhandler: select one item */ 
    self.SelectEventHandler = function (item) { 
     selecteditem(item); 
    }; 

    self.GetReport = function (selectedPerson, viewContainer, url, itemName) { 
     self.selectedPerson(selectedPerson); 
     self.itemname = itemName; 
     var jqxhr = $.ajax({ 
      url: url, 
      type: "GET" 
     }).done(function (data, textStatus, jqXHR) { 
      if (data != null) { 
       self.AddItems(data); 
       $('#' + viewContainer).show(); 
       document.getElementById(viewContainer).scrollIntoView(); 
      } 
     }).fail(function (jqXHR, textStatus, errorThrown) { 
      console.log('fail' + JSON.stringify(jqXHR)); 
      toastr.options = { 
       "closeButton": true, 
       "debug": false, 
       "newestOnTop": false, 
       "progressBar": false, 
       "positionClass": "toast-top-right", 
       "preventDuplicates": false, 
       "onclick": null, 
       "showDuration": "0", 
       "hideDuration": "1000", 
       "timeOut": "0", 
       "extendedTimeOut": "0", 
       "showEasing": "swing", 
       "hideEasing": "linear", 
       "showMethod": "fadeIn", 
       "hideMethod": "fadeOut" 
      }; 
      toastr["error"]("ERROR"); 
     }).always(function (jqXHR, textStatus, errorString) { 
      if (typeof self.searchedCallBackFunction() === 'function') { 
       self.searchedCallBackFunction(); 
      } 
     }); 
    } 
} 

Antwort

1

Es gibt If. Deine Objekte sind einfach und nein t verschachtelt, können Sie den Code schreiben sie selbst zur Karte:

var someJSON = '{ "firstName": "John", "lastName": "Doe" }'; 
 

 
var makeSimpleVM = function(obj) { 
 
    // Return a new object with all property 
 
    // values wrapped in an observable 
 
    return Object 
 
    .keys(obj) 
 
    .reduce(function(vm, key) { 
 
     vm[key] = ko.observable(obj[key]); 
 
     return vm; 
 
    }, {}); 
 
}; 
 

 
var myVM = makeSimpleVM(JSON.parse(someJSON)); 
 

 
console.log(ko.isObservable(myVM.firstName)); // true 
 
console.log(myVM.firstName()); // John 
 

 
myVM.firstName("Jane"); 
 
console.log(myVM.firstName()); // Jane
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

Ich denke, es ist wichtig, durch diese naive Implementierung zu lesen: es macht Sie verstehen, warum es ist wahrscheinlich eine bessere Idee zu verwenden, ein vorgefertigtes Plugin.

Sobald Ihr serverseitiger Code Arrays, verschachtelte Viewmodels oder beliebige Eigenschaften enthält, die Sie nicht zuordnen möchten, werden Sie Probleme bekommen. Das ko.mapping Plugin hat diese Probleme bereits für Sie gelöst. Es ordnet Arrays zu ko.observableArray s zu und Sie können Mapping-Strategien angeben.

var someJSON = '{ "firstName": "John", "lastName": "Doe" }'; 
 

 
// Let's use the library this time 
 
var myVM = ko.mapping.fromJS(JSON.parse(someJSON)); 
 

 
console.log(ko.isObservable(myVM.firstName)); // true 
 
console.log(myVM.firstName()); // John 
 

 
myVM.firstName("Jane"); 
 
console.log(myVM.firstName()); // Jane
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>

Verwandte Themen