Angular 2组件@Input不起作用

82

我在尝试将属性值传递到我的组件中,但一直卡在这里。根据我所阅读的,一切看起来都正确。但它仍然无法正常工作。我的测试值输出到屏幕和控制台上是 null。:(

这是我的测试组件:

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”。

4
模板中不要使用驼峰式命名。HTML不区分大小写。 - alexpods
1
谢谢Alex!我想我必须改掉那个习惯。;0) - Zorthgo
更好的方法是:<testCmp test="Blue32"></testCmp>,您可以删除输入名称周围的方括号,以输入字符串值而不是组件属性。 - webpopular.net
10个回答

152

我可以注意到四件事情:

  • 您正在根组件中传递输入,这将无法工作。
  • 如@alexpods所提到的,您正在使用驼峰命名法,这是不应该的。
  • 您通过[test]传递的是表达式而不是字符串。这意味着angular2正在寻找一个名为Blue32的变量,而不是传递一个原始字符串。
  • 您正在使用构造函数,这将不起作用,它必须在视图已初始化数据绑定属性已初始化之后(请参见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
那个 Plunkr 看起来有问题,在最新的 Chrome/Firefox 上我只看到了 "Test Value:"。 - aikeru
1
@aikeru 谢谢您让我知道。真的很奇怪,plnkr 几乎看起来与答案中的代码不同。无论如何,我已经修复了 :) - Eric Martinez
5
它应该使用帕斯卡命名法(PascalCase),而非驼峰命名法(camelCase)。 - Elfayer
5
对于其他人,解决这个问题的关键是使用 <childcmp [test]="'Blue32'"> 而不是 <childcmp [test]="Blue32">(双引号中的内容)。 - FirstDivision
显示剩余6条评论

18

只需要将字符串用双引号括起来,就像这样:

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

7

如果您使用方括号[],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;

}

6
这个 Angular 类可以处理静态属性: ElementRef https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html

注:ElementRef 是一个 Angular 内置的类,可用于获取对宿主 DOM 的直接访问。
import {ElementRef} from 'angular2/core'

constructor(elementRef: ElementRef) {
    elementRef.nativeElement.getAttribute('api')
}

这就是我一直在寻找的。你是救星 Charles! - gautam1168
谢谢gautam1168。我已经解决了链接过期的问题。 - Charles HETIER

3

分享一下我的经验:

向Angular 4应用程序添加输入

假设我们有两个组件:

  • parent-component
  • child-component

我们想要从parent-componentchild-component传递某些值,即从parent-component.htmlchild-component.ts的一个@Input。以下是一个示例,解释了实现方法:

parent-component.html如下所示:

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

parent-component.ts如下所示:

  
  class ParentComponent {

  someInputValue = 'Some Input Value';

}

child-component.html的内容如下:

<p>一些输入值 {{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中,对象被存储为引用。可以借助Angular 2 / 4来复现这种确切行为。下面是一个解释实现的示例: parent-component.ts 如下所示:
  
  class ParentComponent {

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

}

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

  
{{someInputValue.input}}



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



<p>Some Input Value {{someInputValue}}</p>
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() 函数会改变 ChildComponentParentComponent 中的 someInputValue 值,因为它们是同一个引用。由于 someInputValue 是从 ParentComponentsomeInputValue 对象中引用的 - 在 ChildComponent 中对 someInputValue 对象的更改也会更改 ParentComponentsomeInputValue 对象的值。这是不正确的。引用不应该被更改。


2

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


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进行Angular交互时,始终优先选择以JSON对象的形式从父组件传递数据给子组件,显然这样做不会受到@Angular团队使用本地变量或静态变量的限制。

在访问子组件值的上下文中,无论是构造函数还是ngOnInit(){} Angular生命周期钩子循环,都可以使用

那将帮助您解决问题。 干杯。


0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接