webentwicklung-frage-antwort-db.com.de

Angular 2 Lesen Sie mehr Richtlinie

Ich muss eine Readmore-Direktive in Angular2 erstellen. Mit dieser Anweisung werden lange Textblöcke mit den Links "Lesen" und "Schließen" ausgeblendet und erweitert. Nicht aufgrund der Anzahl der Zeichen, sondern anhand der angegebenen maximalen Höhe.

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

Kann jemand bitte den richtigen Weg angeben, um die Höhe des Elements für diesen speziellen Fall zu ermitteln bzw. festzulegen.

Alle Richtlinien, wie diese spezifische Richtlinie umgesetzt werden könnte, sind ebenfalls sehr zu begrüßen.

Ich muss so etwas bauen https://github.com/jedfoster/Readmore.js

Lösung:

Mit der Hilfe von Andzhik kann ich die folgende Komponente bauen, die meinen Anforderungen entspricht.

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;
        }
    }
}

Verwendungszweck:

<read-more [text]="details" [maxHeight]="250"></read-more>

Wenn Verbesserungen möglich sind, können Sie dies gerne vorschlagen.

11
Naveed Ahmed

Ich denke, dass Sie eine Component brauchen, und nicht Directive. Components ist sinnvoller, da Sie Read more button/link hinzufügen müssen, d. h. DOM aktualisieren.

@Component({
    selector: 'read-more',
    template: `
        <div [class.collapsed]="isCollapsed">
            <ng-content></ng-content>
            <div (click)="isCollapsed = !isCollapsed">Read more</div>
        </div>
    `,
    styles: [`
        div.collapsed {
            height: 250px;
        }
    `]
})

export class ReadMoreComponent {
    isCollapsed = true;
}

Verwendungszweck:

<read-more>
   <!-- you HTML goes here -->
</read-more>
17

Ich habe eine Version erstellt, die die Zeichenlänge anstelle der Größe von div verwendet.

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();       
    }
}

Verwendungszweck: 

<read-more [text]="text" [maxLength]="100"></read-more>
20
jugg1es

Mit der Hilfe von Andzhik kann ich die folgende Komponente bauen, die meinen Anforderungen entspricht.

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;
        }
    }
}

Verwendungszweck:

<read-more [text]="details" [maxHeight]="250"></read-more>
14
Naveed Ahmed
import { Component, Input,OnChanges} from '@angular/core';
@Component({    
    selector: 'read-more',
    template: `
        <div [innerHTML]="currentText"></div>
        <span *ngIf="showToggleButton">
            <a (click)="toggleView()">Read {{isCollapsed? 'more':'less'}}</a>
        </span>`
})

export class ReadMoreDirective implements OnChanges {

    @Input('text') text: string;
    @Input('maxLength') maxLength: number = 100;
    @Input('showToggleButton')showToggleButton:boolean;

    currentText: string;

    public isCollapsed: boolean = true;

    constructor(
        //private elementRef: ElementRef
    ) {

    }
    toggleView() {
        this.isCollapsed = !this.isCollapsed;
        this.determineView();
    }

    determineView() {

        if (this.text.length <= this.maxLength) {
            this.currentText = this.text;
            this.isCollapsed = false;
            return;
        }

        if (this.isCollapsed == true) {
            this.currentText = this.text.substring(0, this.maxLength) + "...";
        } else if(this.isCollapsed == false)  {
            this.currentText = this.text;
        }

    }

    ngOnChanges() {
        if(!this.validateSource(this.text)) {
            //throw 'Source must be a string.';
            console.error('Source must be a string.');
        }
        else{
            this.determineView();
        }
    }

    validateSource(s) {
        if(typeof s !== 'string') {
            return false;
        } else {
            return true;
        }
    }
}

und Verwendung

<read-more [text]="this is test text" [maxLength]="10" [showToggleButton]="true"></read-more>

1
Ipe Himanshu

Sie können dieses Plugin verwenden.

Es ist sehr einfach, nur [text] Und [textLength] Zu übergeben, die Sie standardmäßig anzeigen möchten https://www.npmjs.com/package/nga-read-more

0
DirtyMind

Wenn Sie den Text mit der maximalen Anzahl von Zeichen anzeigen möchten, ohne ein Word zu schneiden, ändern Sie diese Codezeile:

this.currentText = this.text.substring(0, this.maxLength) + "...";

Zu:

this.currentText = this.text.substring(0, this.maxLength);
this.currentText = this.currentText.substr(0, Math.min(this.currentText.length, this.currentText.lastIndexOf(" ")))
this.currentText = this.currentText + "..."
0
D.B

Wiederum habe ich diese Probleme mit dynamischen Daten und vollem Controlling gelöst.

 <div class="Basic-Info-para">
   <p>
     <span *ngIf="personalBasicModel.professionalSummary.length>200" id="dots"> 
         {{personalBasicModel.professionalSummary | slice:0:200}} ...
    </span>
     <span id="more">{{personalBasicModel.professionalSummary }}
</span>
 </p>
</div> 

Hier enthält personalBasicModel.professionalSummary eine Zeichenfolge. wie jeder Text.
slice: 0: 200 = Verwenden Sie das Slice-Pipe für den Verbindungsstring mit 200 Zeichen. Sie können die Länge entsprechend Ihrer Anforderung ändernid = "dots" & id = "more".

<div class="Basic-Info-SeeMore">
            <button class="SeeMore"(click)="showMore(paasValueOn_SeeMoreBtn)">
                {{showLess_More}}
            </button>
        </div>

Hier definieren wir eine Schaltfläche mit dynamischem Text (siehe mehr und weniger) mit Klickereignis.

// ---------------------------------- ts-Datei ------------ ----------------------- //

Variable definieren 

showLess_More: string = "SEE MORE ...";
paasValueOn_SeeMoreBtn: boolean = true;

Ereignis (Methode) wird ausgelöst, wenn der Benutzer auf die Schaltfläche Weitere anzeigen klickt 

 showMore(data:boolean){
    if(data){
      $("#dots").css('display', 'none');
      $("#more").css('display', 'inline');
      this.showLess_More = "SEE LESS ...";
      this.paasValueOn_SeeMoreBtn = false;
    }else{
      $("#dots").css('display', 'inline');
      $("#more").css('display', 'none');
      this.showLess_More = "SEE MORE...";
      this.paasValueOn_SeeMoreBtn = true;

    }

  }

Vielen Dank, ich habe es ein wenig geändert, weil es auf NgOnInit wegen des Konsolenfehlers ist. Es gibt eine kleine Änderung und funktioniert gut mit 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;
  }
 }
}

Wie Sie sehen, habe ich das geändert
const current Height = document.getElementById('textCollapse').offsetHeight;

0
tommyshere

Nur eine kleine Verbesserung des @Andrei Zhytkevich-Codes (Nützlich für Abschriften)

import {
  Component,
  AfterViewInit,
  ViewChild,
  ElementRef,
  Attribute,
  ChangeDetectionStrategy } from '@angular/core';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'ui-read-more',
  template: `
    <div [class.collapsed]="isCollapsed" [style.height]="_height">
      <div #wrapper>
        <ng-content></ng-content>
      </div>
    </div>
    <div class="read-more">
      <button
      type="button"
      class="btn btn-light" (click)="onIsCollapsed()">{{isCollapsed ? 'More' : 'Less'}}</button>
    </div>
  `,
  styles: [`
    :Host{
      display: block;
    }
    .collapsed {
      overflow: hidden;
      padding-bottom: 1rem;
    }
    .read-more{
      display: flex;
      justify-content: flex-end;
    }
  `]
})
export class UiReadMoreComponent implements AfterViewInit{
  @ViewChild('wrapper') wrapper: ElementRef;
  isCollapsed: boolean = true;
  private contentHeight: string;
  private _height: string;
  constructor(@Attribute('height') public height: string = '') {
    this._height = height;
  }
  ngAfterViewInit() {
    this.contentHeight = this.wrapper.nativeElement.clientHeight + 'px';
  }
  onIsCollapsed(){
    this.isCollapsed = !this.isCollapsed;
    this._height = this.isCollapsed ? this.height : this.contentHeight;
  }
}

Verwendungszweck

<ui-read-more height="250px">
 <ngx-md>
    {{post.content}}
 </ngx-md>
</ui-read-more>
0
Whisher

zeilenhöhe Ansatz: -

lineheight und wenig Berechnung und etwas CSS text-overflow: Ellipsis; macht diesen Job.

CSS

.descLess {
  margin-bottom: 10px;
  text-overflow: Ellipsis;
  overflow: hidden;
  Word-wrap: break-Word;
  display: -webkit-box;
  line-height: 1.8;      <==== adjust line-height...a/q to your need
  letter-spacing: normal;
  white-space: normal;
  max-height: 52px;  <==== 250px etc:-
  width: 100%;
  /* autoprefixer: ignore next */
  -webkit-line-clamp: 2; <==== clamp line 2...or 3 or 4 or 5...
  -webkit-box-orient: vertical;
}

.html

    <div class="col-12 rmpm">
          <div id="descLess" *ngIf="seeMoreDesc === 'false'" class="descLess col-12 rmpm">
                {{inputData?.desc}}
           </div>
        <div *ngIf="seeMoreDesc === 'true'" class="col-12 rmpm" style="margin-bottom: 10px;line-height: 1.8;"> 
   <!--Use Line height here-->
                {{inputData?.desc}}
               </div>
        <span class="seeMore" *ngIf="seeMoreDesc === 'false' && lineHeightDesc > 21"
             (click)="updateSeeMore('seeMoreDesc', 'true')">
                 See More
        </span>
        <span class="seeMore" *ngIf="seeMoreDesc === 'true'"
               (click)="updateSeeMore('seeMoreDesc', 'false')">
                   See Less
        </span>
         </div>

.ts

declare const $:any;
seeMoreDesc = 'false';
seeMore = '';
inputData = {
   'desc':'Lorem Ipusme dummy text..................'
 }
 constructor(
        private eRef: ElementRef,
        private cdRef : ChangeDetectorRef
    ) {}
    ngAfterViewChecked() {
       // pass line height here
        this.lineHeightDesc = (Number($('#descLess').height()) / 1.8);
        this.cdRef.detectChanges();
    }


     public updateSeeMore(type, action) {
         if (type === 'seeMoreDesc') {
               this.seeMoreDesc = action;
                this.cdRef.detectChanges();
            } else if (type === 'seeMore') {
                this.seeMore = action;
                this.cdRef.detectChanges();
            }

        }
0
Mahi