Нокаут: ограничение числа символов в наблюдаемом поле
У меня есть наблюдаемое поле имени в моей модели с нокаутом.
Теперь я хочу ограничить количество символов в этом поле, если оно превышает определенное число.
Как будто name = "john smith", и у меня есть предел в 6 символов, а затем
дисплей "john s..."
Ответы
Ответ 1
Другим многоразовым решением является создание настраиваемой привязки, которая отображает обрезанную версию текста.
Это позволяет базовому значению оставаться незатронутым, но обрезает текст для отображения. Это было бы полезно для чего-то вроде предварительного просмотра сообщения или для подбора данных в столбце сетки.
Пример привязки:
ko.bindingHandlers.trimLengthText = {};
ko.bindingHandlers.trimText = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var trimmedText = ko.computed(function () {
var untrimmedText = ko.utils.unwrapObservable(valueAccessor());
var defaultMaxLength = 20;
var minLength = 5;
var maxLength = ko.utils.unwrapObservable(allBindingsAccessor().trimTextLength) || defaultMaxLength;
if (maxLength < minLength) maxLength = minLength;
var text = untrimmedText.length > maxLength ? untrimmedText.substring(0, maxLength - 1) + '...' : untrimmedText;
return text;
});
ko.applyBindingsToNode(element, {
text: trimmedText
}, viewModel);
return {
controlsDescendantBindings: true
};
}
};
Используйте его следующим образом:
<div data-bind="trimText: myText1"></div>
или...
<div data-bind="trimText: myText1, trimTextLength: 10"></div>
Смотрите Fiddle
Ответ 2
<span data-bind="text: (name.length > 6 ? name().substring(0, 5) + '...' : name)"></span>
Или вы можете создать вычисленное наблюдаемое в вашей ViewModel, например:
var self = this;
this.shortName = ko.computed(function() {
return (self.name.length > 6 ? self.name().substring(0, 5) + '...' : self.name);
});
а затем:
<span data-bind="text: shortName"></span>
Ответ 3
Решения Chris Dixon идеальны, если у вас есть одно поле с максимальной длиной. Но если вам придется повторять эту операцию несколько раз, она становится громоздкой. Это когда вы должны написать пользовательский наблюдаемый расширитель, например:
ko.extenders.maxLength = function(target, maxLength) {
//create a writeable computed observable to intercept writes to our observable
var result = ko.computed({
read: target, //always return the original observables value
write: function(newValue) {
var current = target(),
valueToWrite = newValue ? newValue.substring(0, Math.min(newValue.length, maxLength)) : null;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
});
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
Затем вы можете использовать его на любом наблюдаемом, и вы можете указать другую максимальную длину для любого из них. Это устраняет беспорядок из HTML (решение 1) и необходимость записи вычисленного наблюдаемого (решение 2). Вы просто определяете свой наблюдаемый следующим образом:
this.shortName = ko.observable().extend({ maxLength: 25 });
Ответ 4
Если вы хотите усечь значение для числового ввода, которое вы могли бы использовать, и расширитель, который усечет значение, как показано ниже:
ko.extenders.truncateValue = function(target, option) {
target.subscribe(function (newValue) {
if(newValue.length > option){
target(newValue.substring(0,option));
}
});
return target;
};
Затем создайте настраиваемую привязку, которая добавит расширитель к наблюдаемому:
ko.bindingHandlers.maxLength = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
'use strict';
var maxlength = element.getAttribute("maxlength");
valueAccessor().extend({truncateValue: maxlength })
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, viewModel);
}
};
В html вы применяете привязку maxLength следующим образом:
<input type="number" data-bind="maxLength: yourObservable" maxlength="9"></input>