Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Read More Directive

Tags:

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 the basis of the character count but on the basis of the specified max height.

<div read-more [maxHeight]="250px" [innerHTML]="item.details">
</div>

Can anyone please guide what would be the most reliable way to get/set the height of the element for this specific case.

Any guidelines on how this specific directive could be implemented would also be highly appreciated.

I need to build something like this https://github.com/jedfoster/Readmore.js

Solution:

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>

If there could be any improvements, please feel free to suggest.

like image 331
Naveed Ahmed Avatar asked Jun 14 '16 18:06

Naveed Ahmed


People also ask

What is the difference between @component and @directive in Angular?

The Component is used to break up the application into smaller components. That is why components are widely used in later versions of Angular to make things easy and build a total component-based model. The Directive is used to design reusable components, which are more behavior-oriented.

Can we use two structural directive in a single HTML element?

Comparing Component and Structural Directives A component directive can be created multiple times, that is, every component in Angular will have a @Component decorator attached, while we cannot apply more than one structural directive to the same HTML element.

What are directives in angular 2?

A directive is a custom HTML element that is used to extend the power of HTML. Angular 2 has the following directives that get called as part of the BrowserModule module. If you view the app.

What is the naming convention of built in directives in angular 2?

Naming Convention: *[name of directive] — Upper camel case is used for the directive class, while lower camel case is used for the directive's name. What sets them apart from other directives in Angular 2: Reshape DOM structure by adding or removing existing DOM elements and do not have templates.


1 Answers

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>
like image 143
jugg1es Avatar answered Oct 06 '22 00:10

jugg1es