2013-05-01 4 views
12

У меня есть наблюдаемое поле имени в моей модели с нокаутом. Теперь я хочу ограничить количество символов в этом поле, если оно превышает определенное число.Нокаут: ограничение числа символов в наблюдаемом поле

Как будто имя = «Джон Смит» и у меня есть предел 6 символов затем
дисплей «джон s ...»

ответ

18

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

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

Пример связывания:

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> 

See Fiddle

+1

Мне понравилось это решение; Я просто хочу предложить поместить неокрашенный текст в заголовок элемента, чтобы обеспечить быстрый предварительный просмотр исходного значения; что-то вроде «element.title = untrimmedText;» если untrimmedText длина больше, чем maxLength. – CaNNaDaRk

+1

Просто один небольшой комментарий - было бы неплохо проверить, что длина необработанного текста больше (trimTextLenth + 3), потому что если trimTextLenth равно 5, но текст «123456», результатом будет «12345 ...», который длиннее, чем необработанная версия. –

+0

Я использовал ответ Иосифа и комментарий Ивана в этой скрипке: http: //jsfiddle.net/8ypdX/90/. Это создает переменную, называемую truncateText, которая позволяет вам определять текст, используемый для усечения, и измеряет длину этой переменной. Если обрезанный текст плюс текст усечения больше, чем исходная строка, то он не выполняет обрезку. – RussAwesome

15
<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> 
+0

спасибо Крис .. Это работает для меня .. – xyz

+0

я думаю, что в первом примере вы пропустили() после первого '' 'п ame''', как в: '' '' '' – f055

+1

В Knockout вы можете использовать .length без необходимости оценивать выражение с помощью(). –

7

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

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 }); 
+0

Просто, чтобы быть понятным, при записи (установки) наблюдаемого это усечет любые значения, превышающие maxLength, правильно? –

+0

@JosephGabriel точно. – Jalayn

+0

Это решение не ограничивает символы, видимые на входе. – jmathew

2

Если вы хотите усечь значение число i Nput вы могли бы использовать и расширитель, который обрезает значение, как в следующем:

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> 
+0

Я уверен, что 'valueAccessor()' вернет значение свойства 'maxLength', а не значение наблюдаемого, которое вы привязали к элементу. – jmathew

+0

@jmathew надеюсь, что теперь имеет смысл теперь редактировать, я добавил html с привязкой. –

+0

valueAccessor - функция JavaScript, которую вы можете вызвать, чтобы получить текущее свойство модели, которое участвует в этой привязке. Вызовите это без передачи каких-либо параметров (т. Е. Call valueAccessor()), чтобы получить текущее значение свойства модели. Чтобы легко принять как наблюдаемые, так и простые значения, вызовите ko.unwrap по возвращаемому значению. –

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