him
him

Reputation: 3575

How to truncate text in Angular2?

Is there a way that I could limit the length of the string to a number characters? for e.g: I have to limit a title length to 20 {{ data.title }}.

Is there any pipe or filter to limit the length?

Upvotes: 222

Views: 264586

Answers (14)

tbo47
tbo47

Reputation: 3349

import { Pipe, PipeTransform } from '@angular/core'

@Pipe({
    name: 'truncate',
    standalone: true,
})
export class TruncatePipe implements PipeTransform {
    transform(value: string, limit = 10): string {
        if(!value) return ''
        const trail = '...'
        return value.length > limit ? value.substring(0, limit) + trail : value
    }
}

Upvotes: 0

Ketan Akbari
Ketan Akbari

Reputation: 11287

Two way to truncate text into angular.

let str = 'How to truncate text in angular';

1. Solution

  {{str | slice:0:6}}

Output:

   how to

If you want to append any text after slice string like

   {{ (str.length>6)? (str | slice:0:6)+'...':(str) }}

Output:

 how to...

2. Solution(Create custom pipe)

if you want to create custom truncate pipe

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
 name: 'truncate'
})

export class TruncatePipe implements PipeTransform {

transform(value: string, args: any[]): string {
    const limit = args.length > 0 ? parseInt(args[0], 10) : 20;
    const trail = args.length > 1 ? args[1] : '...';
    return value.length > limit ? value.substring(0, limit) + trail : value;
   }
}

In Markup

{{ str | truncate:[20] }} // or 
{{ str | truncate:[20, '...'] }} // or

Don't forget to add a module entry.

@NgModule({
  declarations: [
    TruncatePipe
  ]
})
export class AppModule {}

Upvotes: 589

Amir Dora.
Amir Dora.

Reputation: 2717

Truncate String with Ellipsis

No need any additional pipe, you can use slice.

{{ stringText | slice: 0:25}} {{ stringText.length > 25 ? '...' : ''}}

Upvotes: 9

Mika G.
Mika G.

Reputation: 132

For more flexibilities if we want to truncate from the end or the start (based on @Nika Kasradze) :

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'truncate'
})
export class TruncatePipe implements PipeTransform {

  transform(value: string, args: any[]): string {
    const limit = args.length > 0 ? parseInt(args[1], 10) : 20;
    const trail = args.length > 1 ? args[3] : '...';
    return value.length > limit ? (args[2] === 'start' ? trail : '') + value.substr(args[0], limit) + (args[2] === 'end' ? trail : '') : value;
   }
}

How to use ?

{{ myLongText | truncate:[20, myLongText.length-20, 'start', '...'] }}

Upvotes: 0

Shailesh Ladumor
Shailesh Ladumor

Reputation: 7252

You can truncate text based on CSS. It helps to truncate a text based on width not fix character.

Example

CSS

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

.content {
    width:100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

HTML

<div class="content">
    <span class="truncate">Lorem Ipsum is simply dummied text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</span>
</div>

Note: this code use full for one line not for more than one.

Ketan's Solution is best if you want to do it by Angular

Upvotes: 32

McCoy
McCoy

Reputation: 820

Like this:

{{ data.title | slice:0:20 }}

And if you want the ellipsis, here's a workaround

{{ data.title | slice:0:20 }}...

Upvotes: 24

Eugene P.
Eugene P.

Reputation: 1833

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'truncate',
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, limit: number, trail = '...'): string {
    if (value.length <= limit) {
      return value;
    }

    return value.substring(0, limit - trail.length).replace(/\s+$/, '') + trail;
  }
}
{{ str | truncate: 20 }}
{{ str | truncate: 20:'>>>'] }}

If you need truncate by words:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'truncateByWords',
})
export class TruncateByWordsPipe implements PipeTransform {
  transform(value: string, limit: number, trail = '...'): string {
    if (value.length <= limit) {
      return value;
    }

    const substr = value.substring(0, limit - trail.length).split(' ');
    const isLastWordFull = value
      .split(' ')
      .find(w => w === substr[substr.length - 1]);

    if (isLastWordFull) {
      return substr.join(' ') + trail;
    }

    return substr.slice(0, -1).join(' ') + trail;
  }
}
{{ str | truncateByWords: 20 }}
{{ str | truncateByWords: 20:'>>>'] }}

Upvotes: 0

Shahbaz A.
Shahbaz A.

Reputation: 4356

Limit length based on words

Try this one, if you want to truncate based on Words instead of characters while also allowing an option to see the complete text.

Came here searching for a Read More solution based on words, sharing the custom Pipe i ended up writing.

Pipe:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'readMore'
})
export class ReadMorePipe implements PipeTransform {

  transform(text: any, length: number = 20, showAll: boolean = false, suffix: string = '...'): any {
    
    if (showAll) {
      return text;
    }

    if ( text.split(" ").length > length ) {
      
      return text.split(" ").splice(0, length).join(" ") + suffix;
    }

    return text;
  }

}

In Template:

<p [innerHTML]="description | readMore:30:showAll"></p>
<button (click)="triggerReadMore()" *ngIf="!showAll">Read More<button>

Component:

export class ExamplePage implements OnInit {

    public showAll: any = false;
    
    triggerReadMore() {
        this.showAll = true;
    }
    
}

In Module:

import { ReadMorePipe } from '../_helpers/read-more.pipe';

@NgModule({
  declarations: [ReadMorePipe]
})
export class ExamplePageModule {}

Upvotes: 8

Ignacio Ara
Ignacio Ara

Reputation: 2582

Very simple using slice pipe (angular's core pipe), as you asked for data.title:

{{ data.title | slice:0:20 }}

From Angular common docs https://angular.io/api/common/SlicePipe

Upvotes: 5

cssimsek
cssimsek

Reputation: 1265

Here's an alternative approach using an interface to describe the shape of an options object to be passed via the pipe in the markup.

@Pipe({
  name: 'textContentTruncate'
})
export class TextContentTruncatePipe implements PipeTransform {

  transform(textContent: string, options: TextTruncateOptions): string {
    if (textContent.length >= options.sliceEnd) {
      let truncatedText = textContent.slice(options.sliceStart, options.sliceEnd);
      if (options.prepend) { truncatedText = `${options.prepend}${truncatedText}`; }
      if (options.append) { truncatedText = `${truncatedText}${options.append}`; }
      return truncatedText;
    }
    return textContent;
  }

}

interface TextTruncateOptions {
  sliceStart: number;
  sliceEnd: number;
  prepend?: string;
  append?: string;
}

Then in your markup:

{{someText | textContentTruncate:{sliceStart: 0, sliceEnd: 50, append: '...'} }}

Upvotes: 5

Grey Perez
Grey Perez

Reputation: 20478

Truncate Pipe with optional params:

  • limit - string max length
  • completeWords - Flag to truncate at the nearest complete word, instead of character
  • ellipsis - appended trailing suffix

-

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'truncate'
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, limit = 25, completeWords = false, ellipsis = '...') {
    if (completeWords) {
      limit = value.substr(0, limit).lastIndexOf(' ');
    }
    return value.length > limit ? value.substr(0, limit) + ellipsis : value;
  }
}

Don't forget to add a module entry.

@NgModule({
  declarations: [
    TruncatePipe
  ]
})
export class AppModule {}

Usage

Example String:

public longStr = 'A really long string that needs to be truncated';

Markup:

  <h1>{{longStr | truncate }}</h1> 
  <!-- Outputs: A really long string that... -->

  <h1>{{longStr | truncate : 12 }}</h1> 
  <!-- Outputs: A really lon... -->

  <h1>{{longStr | truncate : 12 : true }}</h1> 
  <!-- Outputs: A really... -->

  <h1>{{longStr | truncate : 12 : false : '***' }}</h1> 
  <!-- Outputs: A really lon*** -->

Upvotes: 118

unos baghaii
unos baghaii

Reputation: 2679

Just tried @Timothy Perez answer and added a line

if (value.length < limit)
   return `${value.substr(0, limit)}`;

to

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'truncate'
})
export class TruncatePipe implements PipeTransform {
transform(value: string, limit = 25, completeWords = false, ellipsis = '...') {

   if (value.length < limit)
   return `${value.substr(0, limit)}`;

   if (completeWords) {
     limit = value.substr(0, limit).lastIndexOf(' ');
   }
   return `${value.substr(0, limit)}${ellipsis}`;
}
}

Upvotes: 1

Kerim092
Kerim092

Reputation: 1497

I've been using this module ng2 truncate, its pretty easy, import module and u are ready to go... in {{ data.title | truncate : 20 }}

Upvotes: 4

Gianfranco P
Gianfranco P

Reputation: 10834

If you want to truncate by a number of words and add an ellipsis you can use this function:

truncate(value: string, limit: number = 40, trail: String = '…'): string {
  let result = value || '';

  if (value) {
    const words = value.split(/\s+/);
    if (words.length > Math.abs(limit)) {
      if (limit < 0) {
        limit *= -1;
        result = trail + words.slice(words.length - limit, words.length).join(' ');
      } else {
        result = words.slice(0, limit).join(' ') + trail;
      }
    }
  }

  return result;
}

Example:

truncate('Bacon ipsum dolor amet sirloin tri-tip swine', 5, '…')
> "Bacon ipsum dolor amet sirloin…"

taken from: https://github.com/yellowspot/ng2-truncate/blob/master/src/truncate-words.pipe.ts

If you want to truncate by a number of letters but don't cut words out use this:

truncate(value: string, limit = 25, completeWords = true, ellipsis = '…') {
  let lastindex = limit;
  if (completeWords) {
    lastindex = value.substr(0, limit).lastIndexOf(' ');
  }
  return `${value.substr(0, limit)}${ellipsis}`;
}

Example:

truncate('Bacon ipsum dolor amet sirloin tri-tip swine', 19, true, '…')
> "Bacon ipsum dolor…"

truncate('Bacon ipsum dolor amet sirloin tri-tip swine', 19, false, '…')
> "Bacon ipsum dolor a…"

Upvotes: 1

Related Questions