2016-08-21 3 views
1

У меня есть два вида деятельности, как это:Нокаут связывание унаследованный JavaScript объекты

function Activity(type, name) { 
    this.Type = type 
    this.Name = ko.observable(name) 
} 

function MeetingActivity(name, place) { 
    Activity.call(this, 1500, name) 
    this.Place = ko.observable(place) 
} 

function TeachingActivity(name, place, teacherId) { 
    Activity.call(this, 1600, name) 
    this.Place = ko.observable(place) 
    this.TeacherId = ko.observable(teacherId) 
} 

и пытаются связать деятельность различных типов в какой-то контейнер, как это:

Activity: 
<select data-bind='value: ActivityTypeId'> 
    <option value='1500'>Meeting</option> 
    <option value='1600'>Teaching</option> 
</select> 
<div data-bind='if: ActivityTypeId()==1500'> 
    <div data-bind='with: Activity'> 
    <span data-bind='text:Name'></span> 
    <span data-bind='text:Place'></span> 
    </div> 
</div> 
<div data-bind='if: ActivityTypeId()==1600'> 
    <div data-bind='with: Activity'> 
    <span data-bind='text:Name'></span> 
    <span data-bind='text:Place'></span> 
    <span data-bind='text:TeacherId'></span> 
    </div> 
</div> 

я написал this fiddle, чтобы получить что делать, но не повезло, что я делаю неправильно?

+0

Да, странная ошибка: "Uncaught TypeError: Невозможно обработать привязку "значение: функция() {вернуться ActivityTypeId}" Сообщение: this.Activity не является функцией" Я проверил что this.Activity определен в поле зрения – user3222589

+1

Как определяется 'ActivityTypeId'? –

+0

Кажется, что ошибка в том, как Knockout обрабатывает 'if' с привязками' when'. Если вы избавитесь от 'with: Activity' и просто используйте' text: Activity(). Name/Place/TeacherId' будет хорошо. – haim770

ответ

0

Проблема с вашим original fiddle вы обновили Activity содержит новый тип, и дисплей изменяется для отображения этого типа, но там будет какое-то время, когда они содержатся тип и тип ожидается для отображения не совпадают.

Для обеспечения отсутствия проблем с синхронизацией, вы должны проверить на Activity.Type (что должно быть наблюдаемым). Кроме того, вместо того, чтобы делать Activity наблюдаемым и подписываясь на изменение его значения, просто сделайте его вычисляемым.

function Activity(type, name) { 
 
    this.Type = ko.observable(type) 
 
    this.Name = ko.observable(name) 
 
} 
 

 
function MeetingActivity(name, place) { 
 
    Activity.call(this, 1500, name) 
 
    this.Place = ko.observable(place) 
 
} 
 

 
function TeachingActivity(name, place, teacherId) { 
 
    Activity.call(this, 1600, name) 
 
    this.Place = ko.observable(place) 
 
    this.TeacherId = ko.observable(teacherId) 
 
} 
 

 
function ViewModel() { 
 
    var self = this 
 
    self.ActivityTypeId = ko.observable(1500); 
 
    self.Activity = ko.computed(
 
    function() { 
 
     var typeId = +self.ActivityTypeId(); 
 

 
     if (typeId == 1500) return new MeetingActivity('meeting 1', 'g12'); 
 
     else if (typeId == 1600) return new TeachingActivity('meeting 2', 'g13', 155); 
 
     else console.warn('Type ID:', typeId); 
 
    }); 
 
} 
 
var VM = null 
 
$(document).ready(function() { 
 
    VM = new ViewModel() 
 
    ko.applyBindings(VM) 
 
    console.log(VM) 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
Activity: 
 
<select data-bind='value: ActivityTypeId'> 
 
    <option value='1500'>Meeting</option> 
 
    <option value='1600'>Teaching</option> 
 
</select> 
 
<div data-bind="with: Activity"> 
 
    <div data-bind='if: Type()==1500'> 
 
    <span data-bind='text:Name'></span> 
 
    <span data-bind='text:Place'></span> 
 
    </div> 
 

 
    <div data-bind='if: Type()==1600'> 
 
    <span data-bind='text:Name'></span> 
 
    <span data-bind='text:Place'></span> 
 
    <span data-bind='text:TeacherId'></span> 
 
    </div> 
 
</div>

+0

Спасибо, Рой Дж, вы попали в решение. – user3222589

0

Ошибка при использовании скрипта от метода subscribe от ActivityTypeId. Помните, что при создании functionthis перезаписывается текущей областью действия функции, поэтому Activity теперь теряется в текущем this.

function ViewModel() { 
    this.ActivityTypeId = ko.observable(1500); 
    this.Activity = ko.observable(new MeetingActivity('meeting 1', 'g12', 155)) 

    this.ActivityTypeId.subscribe(function(typeId) { 
    if (typeId == 1500) this.Activity(new MeetingActivity('meeting 1', 'g12')) 
    else if (typeId == 1600) this.Activity(new TeachingActivity('meeting 2', 'g13', 155)) 
    }) 
} 

Чтобы исправить это, вы можете назначить это другой переменной и получить доступ к ее действию. Как:

function ViewModel() { 
    var self = this; //this is what i meant in assigning in another variable 
    this.ActivityTypeId = ko.observable(1500); 
    this.Activity = ko.observable(new MeetingActivity('meeting 1', 'g12', 155)) 

    this.ActivityTypeId.subscribe(function(typeId) { 
    if (typeId == 1500) self.Activity(new MeetingActivity('meeting 1', 'g12')) //use self on accessing Activity 
    else if (typeId == 1600) self.Activity(new TeachingActivity('meeting 2', 'g13', 155)) //use self on accessing Activity 
    }) 
} 
+0

Спасибо, основная ошибка, которую я собираюсь решить, - это изменение активности от «обучения» до «встречи». error is 'Uncaught ReferenceError: не удалось обработать привязку "text: function() {return TeacherId}" Сообщение: TeacherId не определен' – user3222589

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