角度8:检测ng-content中是否有内容(或存在)

时间:2019-06-25 20:22:28

标签: javascript angular

我有一个组件,该组件的模板允许2个内容区域:文本和“阅读更多”文本。如果组件的使用者添加了“阅读更多”文本的区域,那么我想显示“阅读更多”链接,最终用户将单击该链接以显示文本。如果他们不包含/不需要任何“阅读更多”文字,则我不想显示该链接。

如何检测模板区域的存在,并使用ngIf采取相应措施?

例如,html可能是:

<app-promohero-message-unit title="Title for messaging module">
     <div description>
       Include a short, informative description here.
     </div>
     <div readmoretext>
       If you need to add more detail, include another sentence or two it in this section.
     </div>
</app-promohero-message-unit>

很显然,他们可能不需要readmoretext,因此,如果他们省略了它,则不应该显示readmore链接。

到目前为止,组件代码是:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-promohero-message-unit',
  template: `
    <div>
      <h3 class="text-white">{{ title }}</h3>
      <p class="text-white">
        <ng-content select="[description]"></ng-content>
      </p>
      <p class="text-white" *ngIf="readMore">
        <ng-content select="[readmoretext]"></ng-content>
      </p>
    </div>
    <p>
      <a class="text-white" (click)="showReadMore()" *ngIf="something"><u>Read more</u></a>
    </p>
  `
})
export class PromoheroMessageUnitComponent {
  @Input()
  title: string;

  readMore = false;

  showReadMore() {
    this.readMore = true;
  }
}

3 个答案:

答案 0 :(得分:2)

您可以获得对ng-contentTemplate Variable)的引用,然后使用ViewChild访问组件中的该变量以检查ng-content内容的长度。

然后,您可以使用ngAfterViewInit生命周期挂钩检查ng-content的长度

您的代码将如下所示:

import { Component, Input, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-promohero-message-unit',
  template: `
    <div>
      <h3 class="text-white">{{ title }}</h3>
      <p class="text-white">
        <ng-content select="[description]"></ng-content>
      </p>
      <p class="text-white" *ngIf="readMore">
        <ng-content #readMoreContent select="[readmoretext]"></ng-content>
      </p>
    </div>
    <p>
      <a class="text-white" (click)="showReadMore()" *ngIf="something"><u>Read more</u></a>
    </p>
  `
})
export class PromoheroMessageUnitComponent {
  @Input()
  title: string;
  @ViewChild('readMoreContent') readMoreContent: ElementRef;

  readMore = false;

  ngAfterViewInit() {
    if (this.readMoreContent.nativeElement.childNodes.length.value == 0){
      this.readMore = false
    }
  }

  showReadMore() {
    this.readMore = true;
  }
}

答案 1 :(得分:1)

在Angular 8中,您不必使用ngAfterViewInit生命周期挂钩。只要将viewchild的“静态”值设置为true,就可以使用ngOnInit。

import { Component, OnInit, ViewChild, TemplateRef, ElementRef } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
  @ViewChild('content', { read: ElementRef, static: true }) content: ElementRef;
  constructor() { }

  ngOnInit() {
    console.log(!!this.content.nativeElement.innerHTML);  // return true if there is a content
  }
}

请注意,您必须使用html标签(例如div,span等)包装ng-content指令,并在此外部标签上设置templateRef。

<div #content>
  <ng-content></ng-content>
</div>

我把它放在stackblitz上:https://stackblitz.com/edit/angular-8-communicating-between-components-mzneaa?file=app/app.component.html

答案 2 :(得分:1)

您可以为此使用 the ContentChild decorator,但需要使用带有已定义 ID 的 ng-template 作为您的内容:

<app-promohero-message-unit title="Title for messaging module">
     <div description>
       Include a short, informative description here.
     </div>
     <ng-template #readmoretext>
       If you need to add more detail, include another sentence or two it in this section.
     </ng-template>
</app-promohero-message-unit>

然后在您的组件中,您可以像这样使用 ContentChild 注释:

export class PromoheroMessageUnitComponent {

    @ContentChild('readmoretext')
    readMoreContent: TemplateRef<any>;

    // ...snip
}

最后在你的组件的 HTML 中:

      <!-- snip -->
      <p class="text-white" *ngIf="readMoreContent">
        <ng-container *ngTemplateOutlet="readMoreContent"></ng-container>
      </p>