2013-03-26 3 views
4

Я относительно новичок в KO (начался 2 дня назад) и пытался попробовать несколько простых примеров. В настоящее время у меня проблема с этим фрагментом кода.Knockoutjs не обновляет пользовательский интерфейс в этом случае

<div id="idChangeStyle"> 
    <span data-bind="style: { background: GetAge() < 18 ? 'red':'white'}">Enter Your Age:</span> 
    <input type="text" data-bind="value: GetAge"></input> 
</div> 
function ageViewModel() { 
    var self = this; 
    self.age = ko.observable(18); 
    self.GetAge = ko.computed({ 
     read: function() { 
      return self.age(); 
     }, 
     write: function (value) { 
      value = parseInt(String(value).replace(/[^\d]/g, "")); 
      if (isNaN(value)) 
       self.age(18); 
      else 
       self.age(value); 
     } 
    }); 
}; 
ko.applyBindings(new ageViewModel(), document.getElementById('idChangeStyle')); 

http://jsfiddle.net/WJZqj/

В основном приложение принять один вход (возраст). Я использую записи, доступные для записи, для синтаксического анализа ввода в INTEGER, и после синтаксического анализа, если его NaN я пытаюсь установить для возраста значение по умолчанию , т.е. 18. Также у меня есть простая логика в html, где я меняю фон span на красный цвет, если возраст ниже 18

в нормальном случае он работает нормально, вот когда я получаю в проблему: -

Case 1: 
Current Input: 18 (initial case) 
enter *4* then tab //works 
enter *a* then tab //work (defaults to 18) 
enter *a* then tab //doesn't work 

case 2: 
current input: 18 
enter *a *then tab* //*doesn't work 

Я проверил код нокаута, чтобы увидеть, что происходит в случае, когда после куска прогона кода: -

if(isNaN(value)) 
    self.age(18); 

.. в следующей строке: -

// Ignore writes if the value hasn't changed 
if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) { 

как _latestValue и arguments[0] имеет то же значение (18), так что не делает ничего. Из-за отсутствия изменения значения возраста теперь свойство viewmodel и пользовательский интерфейс не синхронизированы.

Это потому, что я делаю это неправильно?

+0

Вы должны смотреть в использовании [Нокаут Validation] (https: // GitHub.com/ericmbarnard/нокаут-валидация). –

ответ

1

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

С учетом этого, чтобы исправить это, вы должны уведомить подписчиков вручную. Вы можете просто сделать это, вызвав valueHasMutated() на наблюдаемое.

self.GetAge = ko.computed({ 
    read: function() { 
     return self.age(); 
    }, 
    write: function (value) { 
     value = parseInt(String(value).replace(/[^\d]/g, "")); 
     if (isNaN(value)) self.age(18); 
     else self.age(value); 
     self.age.valueHasMutated(); // notify subscribers 
    } 
}); 
+0

yup .. это то, что я искал. большое спасибо. :) BTW Я не вижу этого в любом месте в knockoutjs.com (руководство, документ, примеры и т. Д.), Но теперь заметил это в коде knockoutjs. Изучает код только для того, чтобы узнать/узнать? – miztaken

+0

В этом случае да. К сожалению, все еще есть некоторые функции, которые официально не документированы. Хотя я бы не сказал, что вам нужно действительно _study_, просто взгляните на реализацию, если вы столкнетесь с чем-то, что кажется неправильным, как вы уже делали здесь. –

0

Простой способ обойти это - установить возраст до 0, а затем вернуться к умолчанию.

т.е. изменение:

if(isNaN(value)) { 
    self.age(0); 
    self.age(18); 
} 

Я не знаю, что нокаут счел бы «правильный» способ, но это, вероятно, что я буду делать.

+0

yup .. это делает трюк .. но здесь мы будем называть тот же метод в течение двух раз, чтобы пройти этот тест: - if ((! Observable ['equalComparer]] ||! Observable [' equalComparer '] (_latestValue, arguments [0])) { Мне просто интересно, есть ли какие-то лучшие решения, чем это. – miztaken

2

У меня такая же ситуация, когда я использую нокаутом 3.0. Но эти трики не помогают мне, потому что теперь нокаут уведомлять, только когда вычисляемые значения свойств изменяются.

И я исправить проблему: 1) использовать только уведомить: всегда

function ageViewModel(data) { 
    //notify will should be always, because age is a primitive type 
    this.age = ko.observable(data.age).extend({notify: "always"}); 
    this.GetAge = ko.computed({ 
     read: function() { 
      // notify will should be always, because computed return values of a primitive type. 
      return this.age(); 
     }, 
     write: function (value) { 
      value = parseInt(String(value).replace(/[^\d]/g, "")); 
      if (isNaN(value)) { 
       this.age(18); 
      } 
      else this.age(value); 

     }, 
     owner: this 
    }).extend({notify: "always"}); 

}; 

2) использовать уведомить: всегда и knockout.mapping

function ageViewModel(data) { 
    ko.mapping.fromJS(data, {}, this); 
    //notify will should be always, because age is a primitive type 
    this.age = this.age.extend({notify: "always"}); 
    this.GetAge = ko.computed({ 
     read: function() { 
      // notify will should be always, because computed return values of a primitive type. 
      return this.age(); 
     }, 
     write: function (value) { 
      value = parseInt(String(value).replace(/[^\d]/g, "")); 
      if (isNaN(value)) { 
       this.age(18); 
      } 
      else this.age(value); 

     }, 
     owner: this 
    }).extend({notify: "always"}); 

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