2017-04-25 64 views
0

我有很多(KnockOut)視圖模型從一個rest服務獲取數據,然後填充非常簡單的「item」視圖模型,只包含來自REST接口的字段。Dynamic Item ViewModel Knockout

我只是想知道是否有一種方法不必定義項目viewmodels,但不知何故只是創建它們動態作爲對象(其中每個屬性是可觀察的)。

所以在下面的例子中,我想不要有「ItemViewModel」,但只需在AddItems函數中說它應該基於數據創建一個對象並使每個條目成爲ko.observable。傳遞的「itemName」則包含「ItemViewModel1」(或在其他調用「ItemViewModel2」等)中。

因此,例如,如果JSON的休息輸入有一個字段「LAST_NAME」這將增加self.LAST_NAME = ko.observable()」充滿了價值等。(所以我仍然可以參考它的意見)。

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(); 
      } 
     }); 
    } 
} 

回答

1

沒有如果。你的對象很簡單,沒有牛逼嵌套,您可以編寫代碼來自己把它們映射:

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>

我想通過這個天真的實現閱讀是很重要的:它會讓你明白爲什麼它可能是一個更好的主意,用一個現成的插件

只要您的服務器端代碼包含數組,嵌套視圖模型或您不想映射的任何屬性,就會遇到問題。 ko.mapping插件已經爲您解決了這些問題。它將陣列映射到ko.observableArray s,並讓您指定映射策略。

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>

相關問題