简体   繁体   English

Angular 2,如何将选项从父组件传递到子组件?

[英]Angular 2, How to pass options from parent component to child component?

I have been looking for a solution for this for a while. 我一直在寻找解决方案。 I have tried a bunch of different things from @Input, @Query, dynamicContentLoader, @Inject, @Inject(forwardRef(() but haven't been able to figure this out yet. 我从@ Input,@ Query,dynamicContentLoader,@ Inject,@ Inject(forwardRef(())尝试了很多不同的东西,但还没有想到这个。

My Example Structure: 我的示例结构:

parent.ts parent.ts

import {Component} from 'angular2/core';

@Component({
    selector   : 'my-app',
    directives : [Child],
    template   : `<parent-component></parent-component>`
})

export class Parent
{
    private options:any;

    constructor()
    {
        this.options = {parentThing:true};
    }
}

child.ts child.ts

import {Component} from 'angular2/core';

@Component({
    selector   : 'parent-component',
    template   : `<child-component></child-component>`
})

export class Child
{
    constructor(private options:any) <- maybe I can pass them in here somehow?
    {
        // what I am trying to do is get options from
        // the parent component at this point
        // but I am not sure how to do this with Angular 2
        console.log(options) <- this should come from the parent

        // how can I get parent options here?
        // {parentThing:true}
    }
}

This is my current HTML output in the DOM, so this part is working as expected 这是我在DOM中的当前HTML输出,因此这部分按预期工作

<parent-component>
   <child-component></child-component>
</parent-component>

Question Summarized: 问题总结:

How can I pass options from a parent component to a child component and have those options available in the child constructor? 如何将选项从父组件传递到子组件并在子构造函数中提供这些选项?

Parent to child is the simplest form of all but it's not available in the constructor, only in ngOnInit() (or later). 父对子是最简单的形式,但它在构造函数中不可用,仅在ngOnInit() (或更高版本)中ngOnInit()

This only requires an @Input() someField; 这只需要一个@Input() someField; in the child component and using binding this can be passed from parent to children. 在子组件和使用绑定中,这可以从父组件传递给子组件。 Updates in the parent are updated in the child (not the other direction) 父级更新在子级(而不是其他方向)中更新

@Component({
  selector: 'child-component',
  template'<div>someValueFromParent: {{someValueFromParent}}</div>'
})  
class ChildComponent {
  @Input() someValueFromParent:string;

  ngOnInit() {
    console.log(this.someValue);
  }
}

@Component({
  selector: 'parent-component',
  template: '<child-component [someValueFromParent]="someValue"></child-component>'
})
class ParentComponent {
  someValue:string = 'abc';
}

to have it available in the constructor use a shared service. 让它在构造函数中可用使用共享服务。 A shared service is injected into the constructor of both components. 共享服务被注入到两个组件的构造函数中。 For injection to work the service needs to be registered in the parent component or above but not in the child. 要使注入工作,服务需要在父组件中或以上注册,而不是在子组件中注册。 This way both get the same instance. 这样两者都获得相同的实例。 Set a value in the parent and read it in the client. 在父级中设置一个值并在客户端中读取它。

@Injectable()
class SharedService {
  someValue:string;
}

@Component({
  selector: 'child-component',
  template: '<div>someValueFromParent: {{someValueFromParent}}</div>'
})  
class ChildComponent {
  constructor(private sharedService:SharedService) {
    this.someValue = sharedService.someValue;
  }
  someValue:string = 'abc';
}

@Component({
  selector: 'parent-component',
  providers: [SharedService],
  template: '<child-component></child-component>'
})
class ParentComponent {
  constructor(private sharedService:SharedService) {
    sharedService.someValue = this.someValue;
  }
  someValue:string = 'abc';
}

update 更新

There is not much difference. 没有太大区别。 For DI only the constructor can be used. 对于DI,只能使用构造函数。 If you want something injected it has to be through the constructor. 如果你想要注入的东西,它必须通过构造函数。 ngOnInit() is called by Angular when additional initialization has taken place (like bindings being processed). 当进行额外的初始化(如正在处理的绑定)时,Angular会调用ngOnInit() )。 For example if you make a network call it doesn't matter if you do it in the constructor on in ngOnInit because the call to the server is scheduled for later anyway (async). 例如,如果您进行网络调用,则无论是否在ngOnInit中的构造函数中执行此操作都ngOnInit因为无论如何都会调度对服务器的调用(异步)。 When the current sync task is completed, JavaScript looks for the next scheduled task and processes it (and so on). 当前同步任务完成后,JavaScript将查找下一个计划任务并对其进行处理(依此类推)。 Therefore it's probably so that the server call initiated in the constructor is actually sent after ngOnInit() anyway no matter where you place it. 因此,无论在何处放置,无论如何都可能在ngOnInit()之后实际发送在构造函数中启动的服务器调用。

You could use an @Input parameter: 您可以使用@Input参数:

import {Component,Input} from 'angular2/core';

@Component({
  selector   : 'parent-component',
  template   : `<child-component></child-component>`
})
export class Child {
  @Input()
  options:any;

  ngOnInit() {
    console.log(this.options);
  }
}

Notice that the value of options is available in the ngOnInit and not in the constructor. 请注意, options的值在ngOnInit可用,而不在构造函数中。 Have a look at the component lifecycle hooks for more details: 有关更多详细信息,请查看组件生命周期挂钩:

And provides the options as decribed below: 并提供如下所述的选项:

import {Component} from 'angular2/core';

@Component({
  selector   : 'my-app',
  directives : [Child],
  template   : `<parent-component [options]="options"></parent-component>`
})
export class Parent {
  private options:any;

  constructor() {
    this.options = {parentThing:true};
  }
}

If you want to implement custom events: child triggers an event and the parent register to be notified. 如果要实现自定义事件:子项触发事件并通知父注册。 Use @Output . 使用@Output

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM