2013-04-21 3 views
1

Я попытался выполнить приведенные ниже предложения, но ни один из них не вызывал требуемую реакцию каждый раз, когда значение было обновлено. Это может быть связано с моей реализацией, поскольку я новичок в Knockout.Нокаут - не удается обновить наблюдаемое значение, используя подписку (из-за проверки расширения)

У меня есть наблюдаемое (Amount), которое привязано к TextBoxFor.

@Html.TextBoxFor(m => m.Amount, new { type = "number", data_bind = "value: Amount" }) 

Когда значение введено оно должно быть подтверждено, чтобы обеспечить его не превышает 999999. В дополнение к этому, если значение меньше, чем 50, то оно должно быть установлено до 50. Эти проверки потребности каждый раз, когда изменяется «Сумма».

var viewModel = { 
    Amount: ko.observable().extend({numeric: 0, max: 999999}) 
}; 

Я попытался реализации решения (в ответ на мой предыдущий пост), но я не мог заставить их работать.

Лучшее, что я придумал, заключается в создании вычислений следующим образом. Это проверяет правильность ввода и обновления с первой попытки. Последующие изменения значений не вызывают изменения на экране, а переходят через код, похоже, обновляют значение ViewModel.Amount.

@Html.TextBoxFor(m => m.Amount, new { type = "number", data_bind = "value: amountMin" }) 


quoteVehicleViewModel.VehicleMileage = ko.observable(0); 


viewModel.amountMin = ko.computed({ 
    read: function() { 
     return viewModel.Amount(); 
    }, 
    write: function (value) { 
     if (value < 50) { 
      viewModel.Amount(50); 
     } 
    } 
}).extend({ numeric: 0, max: 999999 }); 

** А «viewModel.Amount()» вошел в консоли показывает значение как 1000, но значение на экране все еще показывает, как введенное значение.

Любая помощь с благодарностью получил

Джон

+0

Большое спасибо за ваш ответ. Джозеф. Я видел, как работала JSFiddle. Я попытался реализовать в своем решении, и пока я вижу, что функция coerceMin работает при загрузке страницы, она не попадает, когда я изменяю значение в текстовом поле. Есть ли что-нибудь еще (от вашего JSFiddle), которое требуется для этого, кроме кода, который вы добавили ниже? – JohnT

+0

Есть скрытая строка 'ko.validation.registerExtenders();', которую я не ввел в фактический фрагмент расширителя в ответе. Вы включили эту строку в свой код? –

+0

Привет. Да, я включил registerExtenders, и код coerceMin запускается при загрузке страницы, а не при вводе значений. Спасибо – JohnT

ответ

1

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

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

Вот пример принуждения расширитель для «мин» правило:

ko.extenders.coerceMin = function (target, enable) { 
     //collect rule values 
     var minRule = ko.utils.arrayFirst(target.rules(), function (val) { 
      return val.rule === "min" 
     }); 
     if (minRule === null) { 
      throw Error("coerceMin extender must be used in conjunction with the 'min' knockout validation rule"); 
     } 
     var minValue = minRule.params; 
     //listen for changes and coerce when necessary 
     var subscription = null; 
     if (enable && !subscription) { 
      subscription = target.subscribe(function (newValue) { 
       if (!isNaN(newValue)) { 
        var newValueAsNum = parseFloat(+newValue); 
        var valueToWrite = newValueAsNum < minValue ? minValue : newValueAsNum; 
        //only write if it changed 
        if (valueToWrite !== newValue) { 
         target(valueToWrite); 
        } 
       } 
      }); 
     } else { 
      if (subscription) { 
       subscription.dispose(); 
      } 
     } 

     //return the original observable 
     return target; 
    }; 

Вы можете применить его в своей модели представления следующим образом:

var viewModel = { 
    Amount: ko.observable() 
       .extend({numeric: 0, min: 50, max: 999999}) 
       .extend({coerceMin: true}); 
}; 

Вот скрипку, чтобы продемонстрировать: http://jsfiddle.net/f2rTR/1/

0

Очень похожая проблема здесь: Make Knockout applyBindings to treat select options as number

Вы могли бы сделать вычисляемое значение, несмотря на подписку. Это будет выглядеть так:

var viewModel = { 
    _amount: ko.observable(100).extend({numeric: 0, max: 999999, reset: true}), 
    Amount : ko.computed(function(){ 
     return _amount < 50 ? 50 : _amount; 
    }) 
}; 


ko.applyBindings(viewModel); 

Редактировать

Я также посмотрел на наполнителях, которые вы использовали здесь. Вы можете добавить к своему значению minender extender и передать его аргумент вашего наблюдаемого. Вы должны явно написать код в методе записи вашего расширитель

что-то вроде:

ko.extenders.numeric = function(target, min) { 
... 
    write:function(v){ 
     ... 
     if(v<50) v=50; 
     ... 
     target(v) 


    } 
... 
} 
+0

Привет там SiMet, спасибо за ваш ответ. У меня было еще несколько вопросов .......... В вашем первом примере, используя вычисляемый вместо подписки, какое значение вы связываете своим значением? например . Я попробовал как _amount, так и Amount, но рассчитанный не был вызван. Есть ли способ реализовать решение расширителей, которое является специфичным для наблюдаемого? Я новичок в KO, но похоже, что ko.extenders.numeric повлияет на все наблюдаемые? благодаря – JohnT

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

  • Нет связанных вопросов^_^