2013-03-18 7 views
2

Hell All,Вопрос с нокаутом подписаться

У меня есть сложная модель с нокаутом с детскими моделями. Ниже приводится определение ViewModel:

var DailyItems = function (data) { 
var p = this; 
this.Date = ko.observable(data.Date); 
this.Required = ko.observable(data.Required); 
this.SetupTime = ko.observable(data.SetupTime); 
this.CloseTime = ko.observable(data.CloseTime); 
this.MinHrsPerDay = ko.observable(data.MinHrsPerDay); 
this.MaxHrsPerDay = ko.observable(data.MaxHrsPerDay); 
this.WorkSegments = ko.observableArray([]); 
var records = $.map(data.WorkSegments, function (x) { return new WorkShift(p, x) }); 
this.WorkSegments(records); 

this.EnableAdd = ko.computed(function() { 
    return this.WorkSegments().length < 8; 
}, this); 

this.Add = function() { 
    var data = { 
     Parent: p, 
     ID: "", 
     Date: this.Date, 
     Location: UNIT_ID, 
     Role: "", 
     EmployeeRoles: this.WorkSegments()[0].EmployeeRoles(),//add the roles of the first work segment 
     ShiftStart: "", 
     ShiftEnd: "" 
    }; 
    var child = new WorkShift(p, data); 
    this.WorkSegments.push(child);  
} 

this.Delete = function (item) { 
    this.WorkSegments.remove(item); 
} 
}; 

var WorkShift = function (parent, data) { 
var self = this; 
this.Parent = ko.observable(parent); 
this.ID = ko.observable(data.ID); 
this.Day = ko.observable(data.Day); 
this.Location = ko.observable(data.Location); 
this.ShiftStart = ko.observable(data.ShiftStart); 
this.ShiftEnd = ko.observable(data.ShiftEnd); 
this.EmployeeRoles = ko.observableArray(data.EmployeeRoles); 

this.Location.subscribe(function (branchId) { 
    $.ajax({ 
     type: "POST", 
     url: SERVER_PATH + '/WebServices/AttributeService.asmx/GetDataOnLocationChange', 
     data: "{" + "clientId: '" + CLIENT_ID 
        + "', unitId: '" + branchId 
        + "', effectiveDate:'" + EFFECTIVE_DATE 
        + "'}", 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     success: function (res) { 
      var d = JSON.parse(res.d); 
      self.EmployeeRoles(d.Roles); 

      var tasks = self.Parent().WorkSegments(); 
      //Requirement: for any day of the week, if there is more than one work segment 
      //at different branches the required type should be set to 'On' and made disable 
      if (tasks.length > 1) { 
       for (var i = 0; i < tasks.length; i++) { 
        if ((d.IsSection == false && tasks[i].Location() != self.Location()) || (d.IsSection == true && self.ParentBranch() != tasks[i].ParentBranch())) { 
         self.Parent().Required('O'); 
        } 
        else { 
         self.Parent().Required('E'); 
        } 
       } 
      } 
     }, 
     error: HandleLocationChangeError 
    }); 
}.bind(this)); 

this.Role = ko.observable(data.Role); 
} 

Что здесь происходит то, что местоположение (наблюдаемое) в DailyItems() представляет собой значение из DropDownList, который заполняется через главный ViewModel. Когда местоположение изменяется, оно должно изменить EmployeeRoles() observablearray в соответствии с выбранным местоположением, следовательно, метод Location.Subscribe.

Моя проблема заключается в том, что этот метод подписки вызывается даже во время начальной загрузки данных. Поэтому вначале есть ненужный вызов на сервер. Я хочу, чтобы он вызывался, когда пользователь действительно меняет выбор.

Какой вариант я должен выполнить для этого?

С уважением, Chathu

+0

Я не вижу, чтобы его вызывали в начальной загрузке. Я пропустил какой-то код? Вот скрипка, которую я создал из того, что вы предоставили. http://jsfiddle.net/sujesharukil/ywEP2/ –

ответ

0

Ниже связывании мой UI:

<tbody data-bind="foreach: WorkSegments"> 
              <tr> 
               <td class="formFields"> 

                ct class="combobox" data-bind="options:$root.WorkLocations, value:Location, optionsText: 'Name', optionsValue: 'ID', enable: LocationActive" 

                 style="font-size: x-small; font-style: normal; font-family: Tahoma; width: 80px"> 
                </select> 
               </td> 
              </tr> 
             </tbody> 

Здесь варианты выпадающие устанавливаются из основного ViewModel. После этого выбранный элемент привязан. После этого, когда я отлаживаю код при начальной загрузке, вызывается метод подписки Location.

1

Передача данных в конструктор WorkShift - это то, что вызывает событие изменения на наблюдаемом месте. Один из подходов состоит в том, чтобы переместить вызов .subscribe на родительский объект после, когда ребенок сконструирован, а наблюдаемое имеет начальное значение.

надстройку функция будет выглядеть примерно так:

this.Add = function() { 
    var data = { 
     // SNIP 
    }; 
    var child = new WorkShift(p, data); 

    child.subscribe(function (branchId) { 
     $.ajax({ 
      // SNIP  
      }); 
    }.bind(child)); // <--- important to use child and not 'this'!!! 

    this.WorkSegments.push(child); 
}; 

Вы бы тогда также должны использовать «это» вместо «я» внутри вызова Ajax, так как вы связали этот контекст ребенка ,

+0

спасибо за ваш ответ, обработка вызова подписки, как это, не будет регистрировать его против существующих объектов WorkShift(), не так ли? Кроме того, если я вызываю вызов подписки на объект WorkShift, как он срабатывает при изменении местоположения? – devC

+0

@chathuranganiePathirage это решение работало для меня в другом проекте. Попробуйте и дайте мне знать, если это сработает для вас. – explunit

0

Может ли быть так просто, как не запустить вызов AJAX, если это первое изменение? Это не красиво, но это просто:

var locationInitialized = false; 
this.Location.subscribe(function (branchId) { 
    if (!locationInitialized) { 
     locationInitialized = true; 
     return; 
    } 
    $.ajax({ 
    ... 

Конечно, вы можете установить locationInitialized в начальной функции успеха населения вместо этого.

В качестве альтернативы, настройте функцию, но не подписывайте ее до тех пор, пока не будет выполнена начальная нагрузка. @explunit показал один из способов сделать это.

Смежные вопросы