2012-08-10 45 views
0

我一直在使用淘汰賽現在幾天,這是我想出組織我的視圖模型和JavaScript型號:如何在更新Knockout.js中的observableArray後立即使用DOM容器?

//****************************************************************************** 
// jQUERY START: 
//****************************************************************************** 
$(document).ready(function() 
{ 
    var panel1 = $('#panel1>section'); 
    var panel2 = $('#panel2>section'); 

    $('#loader').ajaxStart(function() 
    { 
     $(this).fadeIn(); 
    }).ajaxComplete(function() 
    { 
     $(this).fadeOut(); 
    }); 

    ko.applyBindings(new ViewModel(panel1)); 
}); 

//****************************************************************************** 
// VIEW MODEL: 
//****************************************************************************** 
function ViewModel(_panel1) 
{ 
    var self  = this; 
    this.vmHeader = new HeaderViewModel(); 
    this.vmPanel1 = new Panel1ViewModel(_panel1); 
} 

//****************************************************************************** 
// Panel1ViewModel: 
//****************************************************************************** 
function Panel1ViewModel(_element) 
{ 
    var self   = this; 
    self.element  = _element; 
    self.filters  = ['Operations', 'Jobs', 'Shifts', 'Hours']; 
    self.selectedFilter = ko.observable(); 
    self.vmOperations = new OperationsViewModel(); 
    self.vmJobs   = new JobsViewModel(); 
    self.vmShifts  = new ShiftsViewModel(); 
    self.vmHours  = new HoursViewModel(); 

    //PUBLIC METHODS: 
    self.clickFilter = function(filter) 
    { 
     self.selectedFilter(filter); 

     switch(filter) 
     { 
      case 'Operations': 
       self.vmOperations.load(self.clear, self.element); 
       break; 

      case 'Jobs': 
       self.vmJobs.load(self.clear, self.element); 
       break; 

      case 'Shifts': 
       self.vmShifts.load(self.clear, self.element); 
       break; 

      case 'Hours': 
       self.vmHours.load(self.clear, self.element); 
       break; 
     } 
    } 

    self.clear = function() 
    { 
     //test each view model to see if it currently has items loaded and empty them. 
     if (self.vmOperations.operations() != null) { self.vmOperations.operations(null); } 
     if (self.vmJobs.jobs() != null) { self.vmJobs.jobs(null); } 
     if (self.vmShifts.shifts() != null) { self.vmShifts.shifts(null); } 
     if (self.vmHours.hours() != null) { self.vmHours.hours(null); } 
    }; 
} 

//****************************************************************************** 
// ShiftsViewModel: 
//****************************************************************************** 
function ShiftsViewModel() 
{ 
    var self  = this; 
    self.shifts = ko.observableArray(null); 
    self.selected = ko.observable(); 

    //PUBLIC METHODS: 
    self.load = function (callback, element) 
    { 
     var options = { 
      url: '/api/shifts', 
      type: 'GET', 
      data: { 
       operationID: 1 
      } 
     }; 

     async_load(options, function (data) 
     { 
      callback(); 

      self.shifts(
       $.map(data.Items, function (item, index) 
       { 
        return new Shift(item); 
       }) 
      ); 

      element.overscroll(); <--- PROBLEM IS HERE! 
     }); 
    } 

    self.click = function(shift) 
    { 
     self.selected(shift.id); 
    }; 
} 

//****************************************************************************** 
// SHIFT MODEL: 
//****************************************************************************** 
function Shift(data) 
{ 
    var self  = this; 
    this.operation = data.Operation; 
    this.shopOrder = data.ShopOrder; 
    this.date  = data.Date; 
    this.id  = data.ID; 
    this.number = data.Number; 
    this.start  = ko.observable(data.Start); 
    this.end  = ko.observable(data.End); 
    this.isRunning = ko.observable(data.IsRunning); 

    //computed properties. 
    this.shiftDate = ko.computed(function() 
    { 
     var date = (this.end() == '') ? new Date() : new Date(this.end()); 

     return date.toLocaleDateString(); 
    }, this); 

    this.startTime = ko.computed(function() 
    { 
     return (new Date(this.start())).toLocaleTimeString(); 
    }, this); 

    this.endTime = ko.computed(function() 
    { 
     var time = '---'; 

     if (this.isRunning() == 'False') 
     { 
      time = (new Date(this.end())).toLocaleTimeString(); 
     } 

     return time; 
    }, this); 
} 

//****************************************************************************** 
// GLOBAL FUNCTIONS: 
//****************************************************************************** 
function async_load(options, callback) 
{ 
    $.ajax({ 
     url:   options.url, 
     async:   true, 
     cache:   false, 
     type:   options.type, 
     data:   options.data, 
     dataType:  'json', 
     contentType: 'application/json', 
     success: callback, 
     error: function (request, type, errorThrown) 
     { 
      error_handler(options.url, request, type, errorThrown); 
     } 
    }); 
} 

function sync_load(options) 
{ 
    var error = false; 
    var data = $.ajax({ 
     url:   options.url, 
     async:   false, 
     cache:   false, 
     type:   options.type, 
     data:   options.data, 
     dataType:  'json', 
     contentType: 'application/json', 
     error: function (request, type, errorThrown) 
     { 
      error = true; 
      error_handler(options.url, request, type, errorThrown); 
     } 
    }).responseText; 

    if (!error) 
    { 
     data = eval('(' + data + ')'); 
    } 

    return (error) ? null : data; 
} 

function error_handler(name, request, type, errorThrown) 
{ 
    switch (request.status) 
    { 
     case 404: 
      alert('The ' + name + ' could not be found.'); 
      break; 

     case 500: 
      alert('There was an internal server error loading ' + name + '.'); 
      //redirect the user to a page with further instructions. 
      break; 

     default: 
      alert('An error occurred: (' + request.status + ' ' + request.statusText + ').'); 
    } 
} 

這裏是HTML:

 <section id="panel1" data-bind="with: vmPanel1"> 
      <nav data-bind="foreach: filters"> 
       <a href="#" data-bind="text: $data, css: { selected: $data == $root.vmPanel1.selectedFilter() }, click: $root.vmPanel1.clickFilter"></a> 
      </nav> 
      <section> 
       <section id="panel1Data"> 
       <!-- ko foreach: vmOperations.operations --> 
        <article class="operation" data-bind="css: { selected: $data.operationID == $root.vmPanel1.vmOperations.selected() }, click: $root.vmPanel1.vmOperations.click"> 
         <div class="name" data-bind="text: name"></div> 
         <div class="number" data-bind="text: number"></div> 
         <div class="sequence" data-bind="text: sequence"></div> 
        </article>        
       <!-- /ko --> 
       <!-- ko foreach: vmJobs.jobs --> 
        <article data-bind="pageBreak: operation, label: 'operation', level: 1"></article> 
        <article class="job" data-bind="css: { selected: $data.jobID == $root.vmPanel1.vmJobs.selected() }, click: $root.vmPanel1.vmJobs.click"> 
         <div class="start date"> 
          <label data-bind="text: startMonth"></label> 
          <div data-bind="text: startDay"></div> 
          <span data-bind="text: startTime"></span> 
         </div> 
         <div class="end date"> 
          <label data-bind="text: endMonth"></label> 
          <div data-bind="text: endDay"></div> 
          <span data-bind="text: endTime"></span> 
         </div> 
         <div class="shoporder" data-bind="text: shopOrder"></div> 
         <div class="toolconfig" data-bind="toolConfig: $data"></div> 
         <div class="lot" data-bind="text: lot"></div> 
        </article> 
       <!-- /ko --> 
       <!-- ko foreach: vmShifts.shifts --> 
        <article data-bind="pageBreak: operation, label: 'operation', level: 1"></article> 
        <article data-bind="pageBreak: shopOrder, label: 'job', level: 2"></article> 
        <article data-bind="pageBreak: shiftDate(), level: 3"></article> 
        <article class="shift" data-bind="css: { selected: $data.id == $root.vmPanel1.vmShifts.selected() }, click: $root.vmPanel1.vmShifts.click"> 
         <div class="shift" data-bind="text: number"></div> 
         <div class="start time" data-bind="text: startTime()"></div> 
         <div class="end time" data-bind="text: endTime()"></div> 
        </article> 
       <!-- /ko --> 

根據所選的過濾器,適當的數據列表(操作,作業,班次或小時數)將被加載到面板1中,jQuery Overscroll插件用於創建IPad滾動效果。

問題出在調用Overscroll插件的行上的ShiftsViewModel。在調試時,我注意到插件沒有做任何事情,因爲容器元素沒有寬度/高度。在運行程序時,容器會使用正確的數據進行更新,因此在通過Knockout將數據寫入DOM容器之前,看起來好像調用了overscroll。

由於overscroll調用在收到數據後運行的ajax回調中,所以我認爲這樣可以。 Knockout異步更新DOM?我不知道該從哪裏出發......有什麼建議嗎?

回答

0

我想通了這個問題:

在jQuery的準備功能,我被緩存的DOM元素加載任何數據之前,然後用它不具有容器元素裏的任何東西緩存的元素。

於是,我改變了這一點:

var panel1 = $('#panel1>section'); 

到:

var panel1 = '#panel1>section'; 

然後在ShiftsViewModel,我改變了這一行:

element.overscroll(); 

到:

$(element).overscroll(); 

它似乎現在正在工作...

相關問題