【问题标题】:Angular 9: How to get data from parent component in child directiveAngular 9:如何从子指令中的父组件获取数据
【发布时间】:2020-11-11 07:55:56
【问题描述】:

我有一个父组件,里面有子指令。需要从指令中的组件获取输入数据。

<my-parent [data]="'Hello from parent'">
  <input myChild>
</my-parent>

父组件

@Component({
  selector: 'my-parent',
  template: `
    <ng-content select="[myChild]"></ng-content>
  `
})
export class ParentComponent {
  @Input() data: string;
}

儿童指令

@Directive({
  selector: '[myChild]'
})
export class ChildDirective implements OnInit {
  value: string;

  ngOnInit() {
    // needs to get data from parent component here
  }
}

我可以将父组件注入指令,但我不想这样做,因为它增加了循环依赖的风险。

我可以在 ParentComponent 中使用 @ContentChild 并通过公共属性在 AfterContentInit 中传递数据,但我不确定此属性何时可以在 ChildDirective 中使用,我应该在这种情况下使用 AfterContentChecked 吗?

父组件

@ContentChild(ChildDirective, {static: true}) child: ChildDirective;

ngAfterContentInit() {
  this.child.value = this.data;
}

儿童指令

value: string;

ngAfterContentChecked() {
  // will be available data from parent here?
}

也许我应该使用服务在组件和指令之间共享数据?

https://stackblitz.com/edit/angular-pass-data-to-child-directive

【问题讨论】:

    标签: angular angular-directive angular-components angular9


    【解决方案1】:

    您是否有特殊原因需要使用 ng-content 而不是 ng-template?

    我建议你使用 ng-templates 的方法如下

    父组件

    @Component({
      selector: 'my-parent',
      template: `
        <ng-template 
          [ngTemplateOutlet]="child" 
          [ngTemplateOutletContext]="{ $implicit: data }">
        </ng-template>
      `
    })
    export class ParentComponent implements AfterContentInit {
      @Input() data: string;
      @ContentChild(TemplateRef, {static: true}) child: TemplateRef<any>;
    }
    

    儿童指令

    @Directive({
      selector: '[myChild]'
    })
    export class ChildDirective {
      @Input()
      value: string;
    }
    

    用法

    <my-parent [data]="'Hello from parent'">
       <ng-template let-dataThroughParent>
          <input myChild [value]="dataThroughParent" class="form-control">
       </ng-template>
    </my-parent>
    

    重要

    在这种特定情况下(示例),实际上没有必要将数据绑定到您的父级,然后通过模板变量获取它,然后再次将其绑定到您的“myChild”指令,因为这将是多余且不必要的,如果您的用例与此类似,我会将数据直接传递给“myChild”指令,如下所示:

    <my-parent [data]="'Hello from parent'">
       <ng-template>
          <input myChild [value]="'Hello from parent'" class="form-control">
       </ng-template>
    </my-parent>
    

    请注意,它也适用于您的初始方法:

    <my-parent [data]="'Hello from parent'">
      <input myChild [value]="'Hello from parent'">
    </my-parent>
    

    但我假设您确实需要从父级传递在您使用父级的范围内无法访问的数据。这是一个工作示例

    https://stackblitz.com/edit/angular-pass-data-to-child-directive-ebcbg6

    【讨论】:

      【解决方案2】:

      您可以使用@Input() 绑定将数据传递给指令。

      app.component.html

      <my-parent [data]="'Hello from parent'"></my-parent>
      

      my-parent.component.ts

      @Component({
          selector: 'my-parent',
          templateUrl: './my-parent.component.html',
          styleUrls: ['./my-parent.component.scss'],
      })
      export class MyParentComponent implements OnInit {
      
         @Input() data: string;
      }
      

      my-parent.component.html

      <input [myChild]="data"/>
      

      my-child.directive.ts

      @Directive({
        selector: '[myChild]'
      })
      export class ChildDirective implements OnInit {
        value: string;
      
      @Input('myChild') data: string;
      
        ngOnInit() {
            console.log(this.data) // data from parent
        }
      }
      
      
      

      https://angular.io/guide/attribute-directives

      【讨论】:

      • 我认为这是一个答案,它看起来很直观,但是当我尝试它时,实际上 [myChild]="data" 是根据您使用“my-parent”组件的上下文而不是来自“my-parent”组件本身,所以这会导致“data not found”,因为属性数据在“my-parent”之外不存在
      • 我用新的代码示例编辑了答案。我认为当您将input 标签放在my-parent 标签之间时,您可能使用了不正确的语法。我只是不知道角度的这种语法。
      • 这是您要回答的不同用例,在他的问题中,他希望能够根据他在哪里调用它以及他想要什么来为他的“我的父母”组件提供自定义内容使用它,这就是“ng-content”(内容投影)的用途,请查看:blog.angular-university.io/angular-ng-content 它解释得很好。
      • 哦,我以为你问了这个问题。我会阅读你链接的内容。同时,他使用的语法是否有效?
      猜你喜欢
      • 1970-01-01
      • 2020-09-05
      • 2020-12-08
      • 2020-07-10
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多