Angular 2组件@Input无法正常工作


75

我一直试图将属性值传递到组件中。从我阅读的内容来看,一切看起来都是正确的。但是它仍然无法正常工作。我的测试值作为空值输出到屏幕和控制台。:(

这是我的测试组件:

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

@Component({
    selector: 'TestCmp',
    template: `Test Value : {{test}}`
})

export class TestCmp {

    @Input() test: string;

    constructor()
    {
        console.log('This if the value for user-id: ' + this.test);
    }
}

这就是我从父页面调用组件的方式。

<TestCmp [test]='Blue32'></TestCmp>

当页面渲染的测试值为空时。我只看到“测试值:”。

代替“测试值:Blue32”。


3
不要在模板中使用CamelCase名称。HTML不区分大小写。
alexpods 2015年

谢谢亚历克斯!我想我必须改变这个习惯。; 0)
Zorthgo 2015年

Answers:


139

您需要注意四件事:

  • 您正在根组件中传递输入,该输入将不起作用。
  • 如@alexpods所述,您正在使用CamelCase。你不应该。
  • 您正在通过传递表达式而不是字符串[test]。这意味着angular2正在寻找名为的变量,Blue32而不是传递原始字符串。
  • 您正在使用构造函数。这将不起作用,必须在初始化视图之后初始化数据绑定属性(请参阅docs的OnInit)。

因此,经过一些修复,它应该可以正常工作

示例已更新为Beta 1

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

@Component({
  selector : 'childcmp',
  template: `Test Value : {{test}}`
})
class ChildCmp {
    @Input() test: string;
    ngOnInit() {
        console.log('This if the value for user-id: ' + this.test);
    }
}

@Component({
    selector: 'testcmp',
    template : `<childcmp [test]="'Blue32'"></childcmp>`
    directives : [ChildCmp]
})
export class TestCmp {}

bootstrap(TestCmp);

请以这个plnkr为例。

更新资料

我看到人们仍然可以找到答案,因此我将plnkr更新为beta 1,并更正了以下解释:可以在ngAfterViewInit中访问输入,但是可以在ngOnInit的生命周期中更早地访问它们。


1
感谢Eric的帮助!...这些都是非常好的观点。“ AfterViewInit”将真的派上用场。:)
Zorthgo 2015年

那个问题似乎坏了,我在最新的Chrome / Firefox上只能看到“测试值:”。
aikeru 2015年

1
@aikeru感谢您告诉我。真的很奇怪,plnkr几乎不像答案中的代码。无论如何,我已将其修复:)
Eric Martinez

5
它是PascalCase,而不是camelCase。
Elfayer

4
对于其他任何人,此解决方案中为我解决的部分都使用了<childcmp [test]="'Blue32'">代替<childcmp [test]="Blue32">(双引号的内容)
FirstDivision

15

就像用双引号将字符串引起来一样简单,就像这样:

<TestCmp [test]="'Blue32'"></TestCmp>

6

如果使用方括号[],则Angular将使用属性绑定,并期望在引号中包含一个表达式,并且它将从组件类中查找名为“ Blue32”的属性或在模板中查找变量。

如果要将字符串作为值传递给子组件,可以这样传递:

<child-component childProperty='passing string'></child-component>

要么

<child-component [childProperty]="'note double quotes'"></child-component>

然后将其放入child.component.ts中,如下所示:

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

@Component({})
export class ChildComponent {

    @Input()
    childProperty: string;

}


2

我认为这里的问题可能与页面的生命周期有关。因为在构造函数中this.test的值为null。但是,如果我在链接到函数的模板上添加一个按钮,该按钮将值推送到控制台(与我在构造函数中所做的相同),则this.test实际上将具有一个值。


2

分享对我有用的东西:

向Angular 4应用添加输入

假设我们有2个组成部分:

  • parent-component
  • child-component

我们希望将一些值从传递parent-component到,child-component@Inputparent-component.html传递到child-component.ts。以下是一个说明实现的示例:

parent-component.html 看起来像这样:

<child-component [someInputValue]="someInputValue"></child-component>

parent-component.ts 看起来像这样:

  
  class ParentComponent {

  someInputValue = 'Some Input Value';

}

child-component.html 看起来像这样:

<p>Some Input Value {{someInputValue}}</p>

child-component.ts 看起来像这样:


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

@Component({
  selector: 'child-component',
  templateUrl: './child-component.html'
})
export class ChildComponent implements OnInit {

  @Input() someInputValue: String = "Some default value";

  @Input()
  set setSomeInputValue(val) {
    this.someInputValue += " modified";
  }

  constructor() {
    console.log('someInputValue in constructor ************** ', this.someInputValue); //someInputValue in constructor ************** undefined
  }

  ngOnInit() {
    console.log('someInputValue  in ngOnInit ************** ', this.someInputValue); //someInputValue  in ngOnInit ************** Some Input Value
  }
}

请注意,该值的@Input值在内部可用ngOnInit(),而在内部不可用constructor()

Angular 2/4中的对象引用行为

在Javascript中,对象存储为reference

可以在Angular 2/4的帮助下重现此确切行为。以下示例说明了实现:

parent-component.ts 看起来像这样:

  
  class ParentComponent {

  someInputValue = {input: 'Some Input Value'};

}

parent-component.html 看起来像这样:

  
{{someInputValue.input}}



child-component.html 看起来像这样:



Some Input Value {{someInputValue}}

change input

child-component.ts 看起来像这样:


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

@Component({
  selector: 'child-component',
  templateUrl: './child-component.html'
})
export class ChildComponent implements OnInit {

  @Input() someInputValue = {input:"Some default value"};

  @Input()
  set setSomeInputValue(val) {
    this.someInputValue.input += " set from setter";
  }

  constructor() {
    console.log('someInputValue in constructor ************** ', this.someInputValue); //someInputValue in constructor ************** undefined
  }

  ngOnInit() {
    console.log('someInputValue  in ngOnInit ************** ', this.someInputValue); //someInputValue  in ngOnInit ************** Some Input Value
  }

  changeInput(){
    this.someInputValue.input += " changed";
  }
}

该函数changeInput()将更改&someInputValue内的值,因为它们的引用。因为,从引用的对象-在变化的对象的值改变的对象这不是正确的。参考不得更改。ChildComponentParentComponentsomeInputValueParentComponentsomeInputValue ChildComponentsomeInputValue ParentComponentsomeInputValue


1

也许看起来像锤子,但是您可以将输入包裹在这样的对象上:

<TestCmp [test]='{color: 'Blue32'}'></TestCmp>

并改变你的班级

class ChildCmp {
    @Input() test: any;
    ngOnInit() {
        console.log('This if the value for user-id: ' + this.test);
    }
}

1

您必须在子组件的顶部导入这样的输入

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

0

当您使用@Input进行角度交互时,将数据从JSON对象中的父对象传递到子对象始终是首选方法,显然@Angular Team并没有限制它使用局部变量或静态变量。

在上下文中访问子组件上的值时,请使用ngOnInit(){}角度生命挂钩周期,而与构造函数无关。

那会帮助你。干杯。


0

当我遇到这个问题时,实际上只有一个编译错误,我必须首先解决(需要解决循环依赖性)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.