2013-05-01 11 views
12

Ho un campo nome osservabile nel mio modello di visualizzazione ad eliminazione diretta. Ora voglio limitare il numero di caratteri in questo campo se supera il numero certo.Knockout: limite numero di caratteri in un campo osservabile

Come se name = "John Smith" e ho un limite di 6 caratteri, allora
visualizzazione "john s ..."

risposta

18

Un'altra soluzione riutilizzabile è quella di creare un costume vincolante che visualizza una versione tagliata del testo.

Ciò consente al valore sottostante di rimanere inalterato, ma taglia il testo per scopi di visualizzazione. Ciò sarebbe utile per qualcosa come un'anteprima del messaggio o per l'adattamento dei dati in una colonna della griglia.

Esempio di legame:

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 
     }; 
    } 
}; 

usare in questo modo:

<div data-bind="trimText: myText1"></div> 

o ...

<div data-bind="trimText: myText1, trimTextLength: 10"></div> 

See Fiddle

+1

Mi è piaciuta questa soluzione; Vorrei solo suggerire di inserire il testo non modificato nel titolo dell'elemento per fornire un'anteprima veloce del valore originale; qualcosa come "element.title = untrimmedText;" se la lunghezza del testo non tagliata è superiore a maxLength. – CaNNaDaRk

+1

Solo un piccolo commento: sarebbe una buona idea controllare che la lunghezza del testo non programmata sia superiore a (trimTextLenth + 3), perché se trimTextLenth è uguale a 5, ma il testo è "123456", il risultato sarà "12345 ...", che è più lungo della versione non tagliata. –

+0

Ho usato la risposta di Giuseppe e il commento di Ivan su questo violino: http: //jsfiddle.net/8ypdX/90/. Questo crea una variabile chiamata truncateText che consente di definire il testo utilizzato per il troncamento e misura la lunghezza di tale variabile. Se il testo tagliato più il testo del troncamento è più della stringa originale, non esegue il ritaglio. – RussAwesome

15
<span data-bind="text: (name.length > 6 ? name().substring(0, 5) + '...' : name)"></span> 

Oppure si può creare un osservabile calcolato nel vostro ViewModel, come ad come:

var self = this; 

this.shortName = ko.computed(function() { 
    return (self.name.length > 6 ? self.name().substring(0, 5) + '...' : self.name); 
}); 

e poi:

<span data-bind="text: shortName"></span> 
+0

Grazie Chris .. funziona per me .. – xyz

+0

credo che nel vostro primo esempio vi siete persi() dopo il primo '' 'n ame''', come in: '' '' '' – f055

+1

In Knockout puoi usare .length senza dover valutare l'espressione con(). –

7

Chris Dixon le soluzioni sono perfette se hai un campo che ha una lunghezza massima. Ma se devi ripetere questa operazione più volte diventa ingombrante. Questo è quando si dovrebbe scrivere un extender osservabile personalizzato, in questo modo:

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; 
}; 

È quindi possibile utilizzarlo su qualsiasi osservabile, ed è possibile specificare una diversa lunghezza massima per nessuno di loro. Ciò rimuove il disordine dall'HTML (soluzione 1) e la necessità di scrivere un osservabile calcolato (soluzione 2). È sufficiente definire il osservabile nel seguente modo:

this.shortName = ko.observable().extend({ maxLength: 25 }); 
+0

Giusto per essere chiari, quando si scrive su (impostazione) l'osservabile, questo troncherà qualsiasi valore superiore alla lunghezza massima, corretto? –

+0

@JosephGabriel esattamente. – Jalayn

+0

Questa soluzione non limita i caratteri visibili nell'input. – jmathew

2

Se si desidera troncare il valore per un numerico i nput si potrebbe usare e extender che troncherà il valore simile al seguente:

ko.extenders.truncateValue = function(target, option) {        
     target.subscribe(function (newValue) { 
      if(newValue.length > option){ 
       target(newValue.substring(0,option)); 
      }      
     }); 

     return target; 
    }; 

e quindi creare un legame che la volontà personalizzato aggiungerà l'estensione per l'osservabile:

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

Sul tuo html si applica vincolante il maxLength come segue:

<input type="number" data-bind="maxLength: yourObservable" maxlength="9"></input> 
+0

Sono abbastanza sicuro che 'valueAccessor()' restituirà il valore della proprietà 'maxLength' non il valore del parametro osservabile associato all'elemento. – jmathew

+0

@jmathew spero che abbia più senso ora con la modifica, ho aggiunto l'html con la rilegatura. –

+0

valueAccessor - Una funzione JavaScript che è possibile chiamare per ottenere la proprietà del modello corrente coinvolta in questa associazione. Chiamalo senza passare alcun parametro (ad esempio, chiama valueAccessor()) per ottenere il valore della proprietà del modello corrente. Per accettare facilmente valori sia osservabili che semplici, chiama ko.unwrap sul valore restituito. –

Problemi correlati