2016-06-14 6 views
8

私はAngular2でreadmore指令を作成する必要があります。このディレクティブが行うことは、 "続きを読む"と "閉じる"リンクを使用してテキストの長いブロックを折りたたんで展開することです。文字カウントに基づくものではなく、指定された最大高さに基づいています。角2続きを読む

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

この特定のケースの要素の高さを取得/設定する最も信頼できる方法は、誰でもガイドしてください。

この具体的な指令をどのように実装できるかについてのガイドラインも高く評価されます。私は私の要件を満たしている以下のコンポーネントを構築することができる午前Andzhikから助けを借りて

私はこのhttps://github.com/jedfoster/Readmore.js

ソリューションのようなものを構築する必要があります。

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

使用法:

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

任意の改善があるかもしれません場合は、提案すること自由に感じなさい。

+0

のsetTimeout内部currentHeight(_ => {...})は、いくつかのウィンドウを排除する検索角動作の変化の検出中にリサイズの問題が発生します。 http://stackoverflow.com/questions/38930183/angular2-expression-has-changed-after-ws-checked-binding-to-div-width-wi – chenk

答えて

11

Directiveではなく、Componentが必要です。 Componentsは、を追加する必要があるため、意味があります。ボタン/リンクを更新します。つまり、DOMを更新します。

@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: boolean = true; 
} 

使用法:私は私の要件を満たしている以下のコンポーネントを構築することができる午前Andzhikからの助けを借りて

<read-more> 
    <!-- you HTML goes here --> 
</read-more> 
+0

ありがとう、あなたの返事のためのAndzhik。テンプレート:: '

Read more
' スタイル:[ ' divの私は、コンポーネントにいくつかの変更を行いました。折りたたまれた{ 身長:150px; オーバーフロー:非表示。 } '] さらに、 @Input() テキストを追加しました。 しかし、私はまだ表示または非表示にするかどうかを判断できるように、テキストを含むdivの高さを取得する方法が必要です。 –

+0

'ElementRef' http://ngcourse.rangle.io/handout/advanced-components/elementref.htmlを使って、' Component'を表すDOM要素に直接アクセスすることができます。 PS:私の元の答えに満足すれば、それを受け入れてください、ありがとう。 –

+0

私はそれを試みましたが、コンストラクタまたはngAfterContentCheckedでコンソールにログオンすると、未定義のconsole.log(this.el.nativeElement.height)が返されます。私は@HostBinding( 'style.height')プライベートハイトを試しました:文字列;それも未定義です。 –

10

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

使用法:

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

私は文字の長さではなく、divのサイズを使用するバージョンを作りました。

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

使用:

<read-more [text]="text" [maxLength]="100"></read-more> 
+0

ありがとう、それは私が必要としたものでした! – Rodney

+0

htmlタグのコンテンツはどうですか? –

+0

私はそれがhtmlで動作するはずだと思います。 [innerHTML]ディレクティブ – jugg1es

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

および使用

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

関連する問題