Limitar o comprimento de uma sequência com AngularJS

225

Eu tenho o seguinte:

<div>{{modal.title}}</div>

Existe uma maneira de limitar o comprimento da string para dizer 20 caracteres?

E uma pergunta ainda melhor seria: existe uma maneira de alterar a string a ser truncada e mostrar ...no final se tiver mais de 20 caracteres?

Alan2
fonte
3
jsfiddle.net/tUyyx
Ufuk Hacıoğulları

Respostas:

344

Editar A versão mais recente do filtro de AngularJSofertaslimitTo .

Você precisa de um filtro personalizado como este:

angular.module('ng').filter('cut', function () {
        return function (value, wordwise, max, tail) {
            if (!value) return '';

            max = parseInt(max, 10);
            if (!max) return value;
            if (value.length <= max) return value;

            value = value.substr(0, max);
            if (wordwise) {
                var lastspace = value.lastIndexOf(' ');
                if (lastspace !== -1) {
                  //Also remove . and , so its gives a cleaner result.
                  if (value.charAt(lastspace-1) === '.' || value.charAt(lastspace-1) === ',') {
                    lastspace = lastspace - 1;
                  }
                  value = value.substr(0, lastspace);
                }
            }

            return value + (tail || ' …');
        };
    });

Uso:

{{some_text | cut:true:100:' ...'}}

Opções:

  • wordwise (booleano) - se verdadeiro, cortado apenas por limites de palavras,
  • max (número inteiro) - comprimento máximo do texto, cortado para esse número de caracteres,
  • tail (string, padrão: '…') - adicione essa string à string de entrada se a string foi cortada.

Outra solução : http://ngmodules.org/modules/angularjs-truncate (por @Ehvince)

EpokK
fonte
2
Há um equivalente a angulares-módulos: ngmodules.org/modules/angularjs-truncate
Ehvince
angularjs-truncate não é solução, mas sua solução de IS. Obrigado! Faça como módulo!
Anton Bessonov 29/04
@epokk Existe uma maneira de permitir que o usuário, depois de clicar nos três pontos, mostre o texto completo sem cortes? Como um "show more"? Obrigado!
Thales P
isso funciona bem quando usamos dessa maneira {{post.post_content | cut: true: 100: '...'}} Mas falha quando uso assim <span ng-bind-html = "trustHtml (post.post_content | cut: true: 100: '...')"> < / span>, porque eu sou forçado a usá-lo com html confiava no meu caso
S Vinesh
O limite WordWise é um bom recurso que não parece existir no padrão "limitTo"
pdizz
496

Aqui está a correção simples de uma linha sem css.

{{ myString | limitTo: 20 }}{{myString.length > 20 ? '...' : ''}}
Govan
fonte
79
Simples e elegante. Em vez de '...'você também pode usar a entidade HTML para reticências:'&hellip;'
Tom Harrison
provavelmente a solução mais indolor. Lembre-se de que os filtros são relativamente pesados ​​e isso pode ter problemas de desempenho em uma enorme lista de repetições ng! :)
Cowwando
1
impressionante! existe uma maneira de cortar após um número de linhas, em vez de após um número de caracteres?
AXD
@axd Você precisa tentar isso em css ou escrever uma diretiva para conseguir isso.
Govan
1
Esta é a melhor resposta. O resultado do desempenho deve ser insignificante com um número razoável de ng-repeat. Se você está trazendo centenas de ng-repeat com conteúdo que precisa ser truncado, pode ser necessário voltar à prancheta. Resposta agradável, @Govan
erier 21/09/16
59

Sei que está atrasado, mas na versão mais recente do angularjs (estou usando a 1.2.16), o filtro limitTo suporta seqüências de caracteres, bem como matrizes, para que você possa limitar o comprimento da sequência dessa maneira:

{{ "My String Is Too Long" | limitTo: 9 }}

que produzirá:

My String
fino
fonte
9
Esta solução está faltando o "...". O resultado deve ser: "Minha corda ..."
Snæbjørn
Não estou vendo as reticências aqui: plnkr.co/edit/HyAejS2DY781bqcT0RgV?p=preview . Você pode elaborar?
fino
2
O que @ Snæbjørn está dizendo é que a pessoa que fez a pergunta preferiu uma solução que insere "..." no final da sequência truncada. A resposta de Govan faz isso.
Nahn
@ Nahn obrigado por apontar isso. Eu provavelmente deveria ter feito um comentário à resposta do EpokK em vez de outra resposta.
magro
52

Você pode simplesmente adicionar uma classe css à div e adicionar uma dica de ferramenta via angularjs para que o texto aparado fique visível ao passar o mouse.

<div class="trim-info" tooltip="{{modal.title}}">{{modal.title}}</div>

   .trim-info {
      max-width: 50px;
      display: inline-block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;  
      line-height: 15px;
      position: relative;
   }
Sushrut
fonte
4
excesso de texto: reticências, uma ótima.
Chris Russo
4
esta técnica, enquanto incrível, impede o texto de embrulho
Larry
Essa é a resposta correta. Minha regra geral é: "não faça em JavaScript o que pode ser feito em CSS".
Aidan
4
Isso funciona apenas para texto com uma linha por parágrafo. Consulte multilinhas css-tricks.com/line-clampin (nem todos os navegadores suportam isso).
Robert
Isso também funciona se você estiver tentando limitar o comprimento de uma matriz ng-repeat.
chakeda
27

Eu tive um problema semelhante, aqui está o que eu fiz:

{{ longString | limitTo: 20 }} {{longString.length < 20 ? '' : '...'}}
crc442
fonte
Gostaria de remover o espaço em branco entre as duas saídas para evitar quebra de linha
Ignacio Vazquez
21
< div >{{modal.title | limitTo:20}}...< / div>
Thiago Araújo
fonte
Abordagem mais simples, mas funcional. Mas ele pressupõe que todo título teria mais de 20 caracteres e isso, em alguns casos, pode ser inesperado.
Henrique M.
18

Solução mais elegante:

HTML:

<html ng-app="phoneCat">
  <body>
    {{ "AngularJS string limit example" | strLimit: 20 }}
  </body>
</html>

Código angular:

 var phoneCat = angular.module('phoneCat', []);

 phoneCat.filter('strLimit', ['$filter', function($filter) {
   return function(input, limit) {
      if (! input) return;
      if (input.length <= limit) {
          return input;
      }

      return $filter('limitTo')(input, limit) + '...';
   };
}]);

Demo:

http://code-chunk.com/chunks/547bfb3f15aa1/str-limit-implementation-for-angularjs

Anam
fonte
Posso sugerir a adição de um retorno caso o inputvalor seja dinâmico? ie if (!input) {return;}Caso contrário, haverá erros de console JS
mcranston18
1
@ mcranston18 adicionou. Obrigado.
Anam
15

Como precisamos de reticências somente quando o comprimento da string estiver acima do limite, parece mais apropriado adicionar reticências usando do ng-ifque binding.

{{ longString | limitTo: 20 }}<span ng-if="longString.length > 20">&hellip;</span>
mnishiguchi
fonte
7

Existe uma opção

.text {
            max-width: 140px;
            white-space: nowrap;
            overflow: hidden;
            padding: 5px;
            text-overflow: ellipsis;(...)
        }
<div class="text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Excepturi qui soluta labore! Facere nisi aperiam sequi dolores voluptatum delectus vel vero animi, commodi harum molestias deleniti, quasi nesciunt. Distinctio veniam minus ut vero rerum debitis placeat veritatis doloremque laborum optio, nemo quibusdam ad, sed cum quas maxime hic enim sint at quos cupiditate qui eius quam tempora. Ab sint in sunt consequuntur assumenda ratione voluptates dicta dolor aliquid at esse quaerat ea, veritatis reiciendis, labore repellendus rem optio debitis illum! Eos dignissimos, atque possimus, voluptatibus similique error. Perferendis error doloribus harum enim dolorem, suscipit unde vel, totam in quia mollitia.</div>

Aleksandr Havrylov
fonte
7

A solução mais simples que encontrei para limitar o comprimento da string foi {{ modal.title | slice:0:20 }}e, depois, pedir emprestado ao @Govan acima, você pode {{ modal.title.length > 20 ? '...' : ''}}adicionar os pontos de suspensão se a string for maior que 20; portanto, o resultado final é simplesmente:

{{ modal.title | slice:0:20 }}{{ modal.title.length > 20 ? '...' : ''}}

https://angular.io/docs/ts/latest/api/common/index/SlicePipe-pipe.html

maudulus
fonte
4

Aqui está um filtro personalizado para truncar texto. É inspirado na solução do EpokK, mas modificado para minhas necessidades e gostos.

angular.module('app').filter('truncate', function () {

    return function (content, maxCharacters) {

        if (content == null) return "";

        content = "" + content;

        content = content.trim();

        if (content.length <= maxCharacters) return content;

        content = content.substring(0, maxCharacters);

        var lastSpace = content.lastIndexOf(" ");

        if (lastSpace > -1) content = content.substr(0, lastSpace);

        return content + '...';
    };
});

E aqui estão os testes de unidade para que você possa ver como ele deve se comportar:

describe('truncate filter', function () {

    var truncate,
        unfiltered = " one two three four ";

    beforeEach(function () {

        module('app');

        inject(function ($filter) {

            truncate = $filter('truncate');
        });
    });

    it('should be defined', function () {

        expect(truncate).to.be.ok;
    });

    it('should return an object', function () {

        expect(truncate(unfiltered, 0)).to.be.ok;
    });

    it('should remove leading and trailing whitespace', function () {

        expect(truncate(unfiltered, 100)).to.equal("one two three four");
    });

    it('should truncate to length and add an ellipsis', function () {

        expect(truncate(unfiltered, 3)).to.equal("one...");
    });

    it('should round to word boundaries', function () {

        expect(truncate(unfiltered, 10)).to.equal("one two...");
    });

    it('should split a word to avoid returning an empty string', function () {

        expect(truncate(unfiltered, 2)).to.equal("on...");
    });

    it('should tolerate non string inputs', function () {

        expect(truncate(434578932, 4)).to.equal("4345...");
    });

    it('should tolerate falsey inputs', function () {

        expect(truncate(0, 4)).to.equal("0");

        expect(truncate(false, 4)).to.equal("fals...");
    });
});
SharkAlley
fonte
3

Você pode limitar o comprimento de uma sequência ou matriz usando um filtro. Confira este escrito pela equipe do AngularJS.

MAM
fonte
forneça mais alguns detalhes também
Parixit
3

Em html é usado junto com o filtro limitTo fornecido pelo próprio angular como abaixo ,

    <p> {{limitTo:30 | keepDots }} </p>

filter keepDots:

     App.filter('keepDots' , keepDots)

       function keepDots() {

        return function(input,scope) {
            if(!input) return;

             if(input.length > 20)
                return input+'...';
            else
                return input;

        }


    }
Shushanth Pallegar
fonte
3

Se você quiser algo como: InputString => StringPart1 ... StringPart2

HTML:

<html ng-app="myApp">
  <body>
    {{ "AngularJS string limit example" | strLimit: 10 : 20 }}
  </body>
</html>

Código angular:

 var myApp = angular.module('myApp', []);

 myApp.filter('strLimit', ['$filter', function($filter) {
   return function(input, beginlimit, endlimit) {
      if (! input) return;
      if (input.length <= beginlimit + endlimit) {
          return input;
      }

      return $filter('limitTo')(input, beginlimit) + '...' + $filter('limitTo')(input, -endlimit) ;
   };
}]);

Exemplo com os seguintes parâmetros:
beginLimit = 10
endLimit = 20

Antes : - /home/house/room/etc/ava_B0363852D549079E3720DF6680E17036.jar
Depois : - /home/hous...3720DF6680E17036.jar

vhamon
fonte
2
Use this in your html - {{value | limitTocustom:30 }}

and write this custom filter in your angular file,

app.filter('limitTocustom', function() {
    'use strict';
    return function(input, limit) {
        if (input) {
            if (limit > input.length) {
                return input.slice(0, limit);
            } else {
                return input.slice(0, limit) + '...';
            }
        }
    };
});

// if you initiate app name by variable app. eg: var app = angular.module('appname',[])
Mohideen bin Mohammed
fonte
2

Isso pode não ser do final do script, mas você pode usar o css abaixo e adicionar esta classe à div. Isso truncará o texto e também mostrará o texto completo ao passar o mouse. Você pode adicionar mais texto e adicionar um hadler de clique angular para alterar a classe de div no cli

.ellipseContent {
    overflow: hidden;
    white-space: nowrap;
    -ms-text-overflow: ellipsis;
    text-overflow: ellipsis;
}

    .ellipseContent:hover {
        overflow: visible;
        white-space: normal;
    }
Kurkula
fonte
2

Se você tem duas ligações {{item.name}}e {{item.directory}}.

E deseja mostrar os dados como um diretório seguido pelo nome, assumindo '/ root' como o diretório e 'Machine' como o nome (/ root-machine).

{{[item.directory]+[isLast ? '': '/'] + [ item.name]  | limitTo:5}}
Harish Reddy Pothula
fonte
Existe alguma chance de você postar esta resposta na pergunta errada? Isso não parece ter nada a ver com a limitação do comprimento de uma string com o AngularJS.
BSMP 17/08/17
1

Você pode usar este módulo npm: https://github.com/sparkalow/angular-truncate

Injete o filtro truncado no seu módulo de aplicativo da seguinte maneira:

var myApp = angular.module('myApp', ['truncate']); 

e aplique o filtro no seu aplicativo da seguinte maneira:

{{ text | characters:20 }} 
Mel Michael
fonte
1
<div>{{modal.title | slice: 0: 20}}</div>
Vikas
fonte
0

Eu criei essa diretiva que faz isso facilmente, trunca a string até um limite especificado e adiciona uma opção "mostrar mais / menos". Você pode encontrá-lo no GitHub: https://github.com/doukasd/AngularJS-Components

pode ser usado assim:

<p data-dd-collapse-text="100">{{veryLongText}}</p>

Aqui está a diretiva:

// a directive to auto-collapse long text
app.directive('ddCollapseText', ['$compile', function($compile) {
return {
    restrict: 'A',
    replace: true,
    link: function(scope, element, attrs) {

        // start collapsed
        scope.collapsed = false;

        // create the function to toggle the collapse
        scope.toggle = function() {
            scope.collapsed = !scope.collapsed;
        };

        // get the value of the dd-collapse-text attribute
        attrs.$observe('ddCollapseText', function(maxLength) {
            // get the contents of the element
            var text = element.text();

            if (text.length > maxLength) {
                // split the text in two parts, the first always showing
                var firstPart = String(text).substring(0, maxLength);
                var secondPart = String(text).substring(maxLength, text.length);

                // create some new html elements to hold the separate info
                var firstSpan = $compile('<span>' + firstPart + '</span>')(scope);
                var secondSpan = $compile('<span ng-if="collapsed">' + secondPart + '</span>')(scope);
                var moreIndicatorSpan = $compile('<span ng-if="!collapsed">...</span>')(scope);
                var toggleButton = $compile('<span class="collapse-text-toggle" ng-click="toggle()">{{collapsed ? "less" : "more"}}</span>')(scope);

                // remove the current contents of the element
                // and add the new ones we created
                element.empty();
                element.append(firstSpan);
                element.append(secondSpan);
                element.append(moreIndicatorSpan);
                element.append(toggleButton);
            }
        });
    }
};
}]);

E algum CSS para acompanhar:

.collapse-text-toggle {
font-size: 0.9em;
color: #666666;
cursor: pointer;
}
.collapse-text-toggle:hover {
color: #222222;
}
.collapse-text-toggle:before {
content: '\00a0(';
}
.collapse-text-toggle:after {
content: ')';
}
Dimitris
fonte
0

Esta solução é puramente usando ng marca no HTML.

A solução é limitar o texto longo exibido com o link 'mostrar mais ...' no final. Se o usuário clicar no link 'mostrar mais ...', ele mostrará o restante do texto e removerá o link 'mostrar mais ...'.

HTML:

<div ng-init="limitText=160">
   <p>{{ veryLongText | limitTo: limitText }} 
       <a href="javascript:void(0)" 
           ng-hide="veryLongText.length < limitText" 
           ng-click="limitText = veryLongText.length + 1" > show more..
       </a>
   </p>
</div>
Amirul
fonte
0

A SOLUÇÃO MAIS FÁCIL -> que encontrei é deixar o Design de Materiais (1.0.0-rc4) fazer o trabalho. O md-input-containerfará o trabalho para você. Concatiza a string e adiciona elipses, além de ter a vantagem extra de permitir que você clique nela para obter o texto completo, para que fique toda preenchida. Pode ser necessário definir a largura do md-input-container.

HTML:

<md-input-container>
   <md-select id="concat-title" placeholder="{{mytext}}" ng-model="mytext" aria-label="label">
      <md-option ng-selected="mytext" >{{mytext}}
      </md-option>
   </md-select>
</md-input-container>

CS:

#concat-title .md-select-value .md-select-icon{
   display: none; //if you want to show chevron remove this
}
#concat-title .md-select-value{
   border-bottom: none; //if you want to show underline remove this
}
Helzgate
fonte
0

Limitar o número de palavras com um filtro Angular personalizado: Aqui está como eu usei um filtro Angular para limitar o número de palavras exibidas usando um filtro personalizado.

HTML:

<span>{{dataModelObject.TextValue | limitWordsTo: 38}} ......</span>

Código Angular / Javascript

angular.module('app')
.filter('limitWordsTo', function () {
    return function (stringData, numberOfWords) {
        //Get array of words (determined by spaces between words)
        var arrayOfWords = stringData.split(" ");

        //Get loop limit
        var loopLimit = numberOfWords > arrayOfWords.length ? arrayOfWords.length : numberOfWords;

        //Create variables to hold limited word string and array iterator
        var limitedString = '', i;
        //Create limited string bounded by limit passed in
        for (i = 0; i < loopLimit; i++) {
            if (i === 0) {
                limitedString = arrayOfWords[i];
            } else {
                limitedString = limitedString + ' ' + arrayOfWords[i];
            }
        }
        return limitedString;
    }; 
}); //End filter
Geoff
fonte
0

Funciona bem para mim 'In span', ng-show = "MyCtrl.value. $ ViewValue.length> your_limit" ... leia mais. 'extensão final'

GK
fonte
0

Eu uso um bom conjunto de bibliotecas de filtros úteis "Angular-filter" e uma delas chamada "truncate" também é útil.

https://github.com/a8m/angular-filter#truncate

o uso é:

text | truncate: [length]: [suffix]: [preserve-boolean]
Lukas Jelinek
fonte