I need to build a readmore directive in Angular2. What this directive will do is for collapse and expand long blocks of text with \"Read more\" and \"Close\" links. Not on t
You can use this plugin.
It is very simple to use only to pass [text]
and [textLength]
which you want to show by default
https://www.npmjs.com/package/nga-read-more
I made a version that uses character length rather than div size.
import { Component, Input, ElementRef, OnChanges} from '@angular/core';
@Component({
selector: 'read-more',
template: `
<div [innerHTML]="currentText">
</div>
<a [class.hidden]="hideToggle" (click)="toggleView()">Read {{isCollapsed? 'more':'less'}}</a>
`
})
export class ReadMoreComponent implements OnChanges {
@Input() text: string;
@Input() maxLength: number = 100;
currentText: string;
hideToggle: boolean = true;
public isCollapsed: boolean = true;
constructor(private elementRef: ElementRef) {
}
toggleView() {
this.isCollapsed = !this.isCollapsed;
this.determineView();
}
determineView() {
if (!this.text || this.text.length <= this.maxLength) {
this.currentText = this.text;
this.isCollapsed = false;
this.hideToggle = true;
return;
}
this.hideToggle = false;
if (this.isCollapsed == true) {
this.currentText = this.text.substring(0, this.maxLength) + "...";
} else if(this.isCollapsed == false) {
this.currentText = this.text;
}
}
ngOnChanges() {
this.determineView();
}
}
Usage:
<read-more [text]="text" [maxLength]="100"></read-more>
With the help from Andzhik I am able to build the below component that meets my requirements.
import { Component, Input, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'read-more',
template: `
<div [innerHTML]="text" [class.collapsed]="isCollapsed" [style.height]="isCollapsed ? maxHeight+'px' : 'auto'">
</div>
<a *ngIf="isCollapsable" (click)="isCollapsed =! isCollapsed">Read {{isCollapsed? 'more':'less'}}</a>
`,
styles: [`
div.collapsed {
overflow: hidden;
}
`]
})
export class ReadMoreComponent implements AfterViewInit {
//the text that need to be put in the container
@Input() text: string;
//maximum height of the container
@Input() maxHeight: number = 100;
//set these to false to get the height of the expended container
public isCollapsed: boolean = false;
public isCollapsable: boolean = false;
constructor(private elementRef: ElementRef) {
}
ngAfterViewInit() {
let currentHeight = this.elementRef.nativeElement.getElementsByTagName('div')[0].offsetHeight;
//collapsable only if the contents make container exceed the max height
if (currentHeight > this.maxHeight) {
this.isCollapsed = true;
this.isCollapsable = true;
}
}
}
Usage:
<read-more [text]="details" [maxHeight]="250"></read-more>
Thank you, I changed it up a bit for it be on NgOnInit because of the console error. There's a slight change to it and works well with Angular 6.
@Component({
selector: 'app-read-more',
template: `
<div id="textCollapse" [innerHTML]="text" [class.collapsed]="isCollapsed" [style.height]="isCollapsed ? maxHeight+'px' : 'auto'">
</div>
<a *ngIf="isCollapsible" (click)="isCollapsed =! isCollapsed">Read {{isCollapsed ? 'more':'less'}}</a>
`,
styles: [`
div.collapsed {
overflow: hidden;
}
a {
color: #007bff !important;
cursor: pointer;
}
`]
})
export class ReadMoreComponent implements OnInit {
// the text that need to be put in the container
@Input() text: string;
// maximum height of the container
@Input() maxHeight: number;
// set these to false to get the height of the expended container
public isCollapsed = false;
public isCollapsible = false;
constructor(private elementRef: ElementRef) {
}
ngOnInit() {
const currentHeight = document.getElementById('textCollapse').offsetHeight;
if (currentHeight > this.maxHeight) {
this.isCollapsed = true;
this.isCollapsible = true;
}
}
}
As you can see I changed the
const current Height = document.getElementById('textCollapse').offsetHeight;