-
-
Save AitorAlejandro/87a57fd7a34f539d0f101ef86b0693a6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from '@angular/core'; | |
@Directive({ | |
selector: '[appReadMore]' | |
}) | |
export class ReadMoreDirective implements AfterViewInit { | |
@Input() limit : number = 50; //to get the custom text limit | |
@Input() toggle : boolean = false; //true: 'Read Less' button will be present | |
txtSpan! : HTMLSpanElement; | |
btnSpan! : HTMLSpanElement; | |
listeners : any[] = []; //add event listeners to unsubscribe all at the end | |
constructor(private el : ElementRef, | |
private renderer : Renderer2) {} | |
ngAfterViewInit(): void { | |
//step 1 ---> change the text in HTML DOM element (<p>, <div>, <span>, <h1>, etc) | |
let text : string = this.el.nativeElement.innerHTML; | |
if(text.length > (this.limit)) //perform below logic only when text length exceeds limit | |
{ | |
this.renderer.setProperty(this.el.nativeElement, 'innerHTML', text.substring(0,this.limit)); | |
//step 2 ---> create txtSpan(remaining text) and btnSpan(Read More button) | |
this.txtSpan = this.renderer.createElement('span'); | |
this.btnSpan = this.renderer.createElement('span'); | |
//step 3 ---> set initial properties and styles for both span elements | |
this.renderer.setProperty(this.txtSpan, 'innerHTML', text.substring(this.limit)); | |
this.renderer.setStyle(this.txtSpan, 'display', 'none'); | |
this.renderer.setProperty(this.btnSpan, 'innerHTML', 'Read More'); | |
//below css properties are optional | |
this.renderer.setStyle(this.btnSpan, 'cursor', 'pointer'); | |
this.renderer.setStyle(this.btnSpan, 'margin-left', '1ch'); | |
this.renderer.setStyle(this.btnSpan, 'text-decoration', 'underline'); | |
//step 4 ---> add onClick handler for 'Read More' button span | |
if(this.toggle) //case when toggling needs to be enabled | |
this.listeners.push(this.renderer.listen(this.btnSpan, 'click', () => { | |
if(this.txtSpan.style.display == 'none') //case when the text is hidden(default case) | |
{ | |
this.renderer.setStyle(this.txtSpan, 'display', 'inline'); | |
this.renderer.setProperty(this.btnSpan, 'innerHTML', 'Read Less'); | |
} | |
else //case when the text is visible | |
{ | |
this.renderer.setStyle(this.txtSpan, 'display', 'none'); | |
this.renderer.setProperty(this.btnSpan, 'innerHTML', 'Read More'); | |
} | |
})); | |
else //case when toggling is off (only show text) | |
this.listeners.push(this.renderer.listen(this.btnSpan, 'click', () => { | |
this.renderer.setStyle(this.txtSpan, 'display', 'inline'); | |
this.renderer.setStyle(this.btnSpan, 'display', 'none'); | |
})); | |
//step 5 ---> append both span to the HTML DOM element | |
this.renderer.appendChild(this.el.nativeElement, this.txtSpan); | |
this.renderer.appendChild(this.el.nativeElement, this.btnSpan); | |
} | |
} | |
ngOnDestroy(): void { | |
this.listeners.forEach(val => val()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment