从角度组件选择器获取内部文本

时间:2017-11-25 04:30:05

标签: angular

我正在构建一个Angular消息组件:

<app-info-card>
  my message here
</app-info-card>

这是我的组成部分:

import {AfterViewInit, Component, ContentChild, ElementRef, Input, OnInit} from '@angular/core';

@Component({
  selector: 'app-info-card',
  templateUrl: './info-card.component.html',
  styleUrls: ['./info-card.component.css']
})
export class InfoCardComponent implements OnInit, AfterViewInit {

  @ContentChild('app-info-card') messageRef: ElementRef;
  message: string;

  constructor() {
  }

  ngOnInit() {
  }

  ngAfterViewInit() {

    this.message = this.messageRef.nativeElement.innerHTML;
    console.log(this.messageRef.nativeElement.innerHTML);

  }

}

这给了我一个错误,即messageRef未定义。我试图从组件选择器中获取内部文本&#34;我的消息在这里&#34;进入组件的消息字段。有没有办法可以在不添加属性的情况下执行此操作?

5 个答案:

答案 0 :(得分:1)

你基本上以一种奇怪的方式使用ContentChild。您正在引用“app-info-card&#39;本身就是它自己的孩子。来自docs

  

您可以使用ContentChild从内容DOM中获取与选择器匹配的第一个元素或指令。如果内容DOM发生更改,并且新子项与选择器匹配,则将更新该属性。

因此,如果您想在组件中放入一些组件/指令并希望以后访问它们,您可以使用ContentChildContentChildren,方式如下:(来自同一个再次链接)

@Directive({selector: 'pane'})
export class Pane {
  @Input() id: string;
}

@Component({
  selector: 'tab',
  template: `
    <div>pane: {{pane?.id}}</div> 
  `
})
export class Tab {
  @ContentChild(Pane) pane: Pane;
}


@Component({
  selector: 'example-app',
  template: `
    <tab>
      <pane id="1" *ngIf="shouldShow"></pane>
      <pane id="2" *ngIf="!shouldShow"></pane>
    </tab>

    <button (click)="toggle()">Toggle</button>
  `,
})
export class ContentChildComp {
  shouldShow = true;

  toggle() { this.shouldShow = !this.shouldShow; }
}

话虽如此,您可以将其与类名称一起使用,而不是使用选择器string。像这样的东西:

@ContentChild(InfoCardComponent) messageRef: InfoCardComponent;

正如我所说,这是一件奇怪的事情,并且会给你InfoCardComponent组件本身。

无论如何,如果你只想拥有一个包裹元素块的组件,你可以做出两件事:

1-使用@Input

如果你只想包装一些文字并以特殊风格展示,你可以简单地拥有一个属性:

@Input() myMessage: string;

并在使用InfoCardComponent时传递它的值:

<app-info-card [myMessage]="'my message here'"></app-info-card>

然后通过你想要的任何地方绑定来使用它......

2-使用<ng-content></ng-content>

如果你想传入组件,不仅仅是文本和包含元素(如<div>和...),你可以使用内置的<ng-content></ng-content>指令包含放在初始主机元素中的所有内容(在这种情况下,将是您的<app-info-card></app-info-card>)。它的工作方式是你只需将它放在你的模板中,如:

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

所有这些方式都有许多细节,并根据您的需要适合某些情况,我刚才提到了使用它们的简短案例。在使用其中任何一个之前,我建议你再次阅读文档。

答案 1 :(得分:1)

我知道这个问题很老,但我找到了这个问题的解决方案,而没有引入额外的(内部/包装的)组件指令。

在需要以字符串形式访问内容的组件模板内部,需要使用ng-templateng-content的包装组合。然后,使用 ViewChild 抓取指向模板的指针。诀窍是模板不会自行呈现,而其内容仍会填充。

需要内容为字符串而不渲染它的组件的模板:

<ng-template #template>
  <ng-content></ng-content>
</ng-template>

在同一个组件的 ts 代码中,您将内容作为 TemplateRef 获取,您可以将其呈现在您想要的任何位置:

@ViewChild('template') templateRef!: TemplateRef<unknown>;

最后,您可以完全按照自己的意愿传递内容:

<app-info-card>
  my message here
</app-info-card>

答案 2 :(得分:0)

根据您的回答,您需要将该消息传递到您的子组件中。有不同的方法,请看https://angular.io/guide/component-interaction

我建议您在这种情况下使用输入绑定。 使用父模板中的变量

while (guess != theNumber) {
                    try {                       
                        System.out.println("Guess a number between 1 and 100:");
                        guess = scan.nextInt(); // Reads the number typed on the
                        // keyboard by the player
                        count++; // Plus 1 every time a number is entered
                        System.out.println("You entered " + guess + ".");
                        if (guess < theNumber) { // If number entered is smaller
                            System.out.println("The number is bigger" + ", try again!");
                            System.out.println("Number of tries: " + count);
                        } else if (guess > theNumber) { // If number entered is
                            // bigger
                            System.out.println("The number is smaller" + ", try again!");
                            System.out.println("Number of tries: " + count);
                        } else { // If both previous cases are false
                            System.out.println("Congratulations! You've found the number!");
                        }
                    } catch (Exception e) {
                        System.out.println("Incorrect entering! Please enter a number between 1 and 100.");
                        scan = new Scanner(System.in);
                    }
                }

您在相应组件中的位置

<app-info-card [message]="message"></app-info-card>

或直接如果它不是动态的(可能不是这种情况)

private message: string = 'my message here';

注意&#39;内部

您的子组件中的两种方式都是这样的:

<app-info-card [message]="'my message here'"></app-info-card>

您可能也希望实现OnChanges。如果您还有其他问题,请与我们联系。

答案 3 :(得分:0)

正如@GHB所提到的,我设法使用指令使它起作用。似乎很难直接使用组件的内容,但是通过使用包装指令可以实现。

import { Component, OnInit, ContentChild, AfterContentInit, ElementRef, Directive } from '@angular/core';

@Directive({
  selector: 'app-example-code'
})
export class ExampleCodeDirective {}

@Component({
  selector: 'app-example-view',
  templateUrl: './example-view.component.html',
  styleUrls: ['./example-view.component.css']
})
export class ExampleViewComponent implements OnInit, AfterContentInit {  
  @ContentChild(ExampleCodeDirective, { read: ElementRef })
  content: ElementRef;

  constructor() { }

  ngAfterContentInit() {
    if (this.content) {
      console.log(this.content.nativeElement.innerText); 
    }
  }

  ngOnInit() {
  }

}

<app-example-view>
  <app-example-code>
    some text
  </app-example-code>
</app-example-view>

答案 4 :(得分:0)

-Dotel.traces.exporter=jaeger
-Dotel.metrics.exporter=none
-Dotel.exporter.jaeger.endpoint=http://localhost:14250
-Dotel.resource.attributes=service.name=myService
-javaagent:C:/path/to/opentelemetry-javaagent-1.0.1-all.jar