Angular 从服务加载数据并使用@Input传递给子组件

Angular 从服务加载数据并使用@Input传递给子组件,angular,Angular,我使用自定义的DataServiceangular服务来获取一些强类型的multi-languagetext数据,这些数据保存在我的phrase字段中。然后我想使用@Input将其传递给子组件 我尝试在ngOnInit和ngOnChangeslifecycle(请参见代码)钩子处加载数据,但在这两种情况下,我的子组件都会收到未定义的 当硬编码短语值时,它会起作用,这告诉我,在我已经向子组件发送了未定义的值之后,数据从服务加载 <child-component [phrase]="this

我使用自定义的
DataService
angular服务来获取一些强类型的
multi-languagetext
数据,这些数据保存在我的
phrase
字段中。然后我想使用
@Input
将其传递给子组件

我尝试在
ngOnInit
ngOnChanges
lifecycle(请参见代码)钩子处加载数据,但在这两种情况下,我的子组件都会收到
未定义的

当硬编码
短语
值时,它会起作用,这告诉我,在我已经向子组件发送了
未定义的
值之后,数据从服务加载

 <child-component [phrase]="this.phrase"></child-component>
相关类型

export class MultiLanguageText {
  de: string;
  fr: string;
  en: string;
}
父模板:

<child-component [phrase]="this.phrase">
</child-component>
/* imports & meta data omitted for readability */

export class ParentComponent implements OnChanges {

  phrase: MultiLanguageText;

  constructor(private dataService: DataService) {}

  ngOnChanges(): void {
    this.dataService.getData().then((d) => {
      this.phrase = d;
      console.log(this.phrase); // logs correct data
    });
  }
}
<p>{{this.phrase.en}}</p>
/* imports & meta data omitted for readability */

export class ChildComponent {

  @Input() phrase: MultiLanguageText;

  constructor() {
    console.log("phrase equals: ", this.phrase); // logs `undefined`, why?
  }
}
/* imports & meta data omitted for readability */

export class ChildComponent {

  @Input() phrase: MultiLanguageText;

  constructor() {
    console.log("phrase equals: ", this.phrase); // logs `undefined`
  }

  ngOnChanges(): void {
    console.log("phrase equals: ", this.phrase); // logs correct data, yay!
  }
}
子模板:

<child-component [phrase]="this.phrase">
</child-component>
/* imports & meta data omitted for readability */

export class ParentComponent implements OnChanges {

  phrase: MultiLanguageText;

  constructor(private dataService: DataService) {}

  ngOnChanges(): void {
    this.dataService.getData().then((d) => {
      this.phrase = d;
      console.log(this.phrase); // logs correct data
    });
  }
}
<p>{{this.phrase.en}}</p>
/* imports & meta data omitted for readability */

export class ChildComponent {

  @Input() phrase: MultiLanguageText;

  constructor() {
    console.log("phrase equals: ", this.phrase); // logs `undefined`, why?
  }
}
/* imports & meta data omitted for readability */

export class ChildComponent {

  @Input() phrase: MultiLanguageText;

  constructor() {
    console.log("phrase equals: ", this.phrase); // logs `undefined`
  }

  ngOnChanges(): void {
    console.log("phrase equals: ", this.phrase); // logs correct data, yay!
  }
}
更新1:添加了
ngOnChanges
HOOK-TO-CHILD组件:

<child-component [phrase]="this.phrase">
</child-component>
/* imports & meta data omitted for readability */

export class ParentComponent implements OnChanges {

  phrase: MultiLanguageText;

  constructor(private dataService: DataService) {}

  ngOnChanges(): void {
    this.dataService.getData().then((d) => {
      this.phrase = d;
      console.log(this.phrase); // logs correct data
    });
  }
}
<p>{{this.phrase.en}}</p>
/* imports & meta data omitted for readability */

export class ChildComponent {

  @Input() phrase: MultiLanguageText;

  constructor() {
    console.log("phrase equals: ", this.phrase); // logs `undefined`, why?
  }
}
/* imports & meta data omitted for readability */

export class ChildComponent {

  @Input() phrase: MultiLanguageText;

  constructor() {
    console.log("phrase equals: ", this.phrase); // logs `undefined`
  }

  ngOnChanges(): void {
    console.log("phrase equals: ", this.phrase); // logs correct data, yay!
  }
}
子组件代码:

<child-component [phrase]="this.phrase">
</child-component>
/* imports & meta data omitted for readability */

export class ParentComponent implements OnChanges {

  phrase: MultiLanguageText;

  constructor(private dataService: DataService) {}

  ngOnChanges(): void {
    this.dataService.getData().then((d) => {
      this.phrase = d;
      console.log(this.phrase); // logs correct data
    });
  }
}
<p>{{this.phrase.en}}</p>
/* imports & meta data omitted for readability */

export class ChildComponent {

  @Input() phrase: MultiLanguageText;

  constructor() {
    console.log("phrase equals: ", this.phrase); // logs `undefined`, why?
  }
}
/* imports & meta data omitted for readability */

export class ChildComponent {

  @Input() phrase: MultiLanguageText;

  constructor() {
    console.log("phrase equals: ", this.phrase); // logs `undefined`
  }

  ngOnChanges(): void {
    console.log("phrase equals: ", this.phrase); // logs correct data, yay!
  }
}
到目前为止,很好,我现在可以从子组件的控制器访问正确的数据。但是,在模板中,它仍然使用“原始”
未定义的值,如何强制模板使用新可用的有效数据

更新2:使用方法获取
短语.en
数据


正如@Riron所指出的,
phrase
变量是异步设置的,因此在构造子项时,
phrase
的值仍然是
未定义的。
只要加载
短语
数据,就可以在模板中使用它。我解决这个问题的方法是在控制器中使用一种方法:

getPhrase = () => {
    return this.phrase === undefined ? "" : this.phrase.en;
}
getPhrase = () => {
    return this.phrase === undefined ? "" : this.phrase.en;
}
然后我会从模板中调用它:

<p>{{ getPhrase() }}</p>
<p>{{ getPhrase() }}</p>
{{getPhrase()}

1)使用组件中的参数时,不需要使用此选项

 <child-component [phrase]="this.phrase"></child-component>

2) 绑定也是如此

<p>{{phrase}}</p>
{{phrase}


您的
短语
变量是异步设置的,因此在构造子项时,
短语
的值仍然是
未定义的

如果在子组件而不是父组件上实现
ngOnChanges
,您应该会在某个点看到值(不是在第一次检查时):


正如@Riron所指出的,
phrase
变量是异步设置的,因此在构造子项时,
phrase
的值仍然是
未定义的。
只要加载
短语
数据,就可以在模板中使用它。我解决这个问题的方法是在控制器中使用一种方法:

getPhrase = () => {
    return this.phrase === undefined ? "" : this.phrase.en;
}
getPhrase = () => {
    return this.phrase === undefined ? "" : this.phrase.en;
}
然后我会从模板中调用它:

<p>{{ getPhrase() }}</p>
<p>{{ getPhrase() }}</p>
{{getPhrase()}


您也需要在
激励驱动程序表单组件上实现
一次更改
,并检查其
一次更改
生命周期挂钩中的更改。@echonax感谢您的评论,您是否介意使用一个代码示例来澄清您的观点?我不确定这会是什么样子。它就像你的
ParentComponent
一样,只需像Riron一样对它执行
ngOnChanges
answer@echonax谢谢,是的,这是有效的,但是,我仍然不明白我现在如何通知模板有效值可用。信息表单哪个模板?虽然你说的是真的,这与所问的问题无关。谢谢,RRIN这有点帮助,但是,模板仍然没有显示有效的价值之后,它是可用的(也请考虑我的更新问题)。你删除了<代码>这个< /代码>在您的模板?您只需要在JS中使用它们code@Riron您应该通过从模板中删除
this
来编辑您的答案,以显示您的意思。@Riron@echonax是的,我确实删除了
this
。Sry,错误在于我在操作中遗漏了太多内容。在我的子模板中,我评估了
{{phrase.en}
,最初,当
短语
仍然是
未定义
时,它将没有
en
属性。我用一个getter来解决它:
getPhrase=()=>{返回this.phrase===未定义?“:this.phrase[this.language];}
对不起,我的错。