【问题标题】:Angular Elements: @Input decorator not working with variablesAngular Elements:@Input 装饰器不适用于变量
【发布时间】:2019-03-03 14:22:22
【问题描述】:

我有几个独立的 Web 组件,由 angular 元素组成,我将它们导入到一个主组件中,它有一个路由器并且是基础应用程序。 路线很简单:

import { Component } from '@angular/core';
import { Router } from "@angular/router";

@Component({
    selector: 'example',
    template: '<component-one [variable]="toPass" (callback)="onCallback($event)"></component-one>',
    styles: []
})
export class ExampleComponent {
    public toPass: string = "Hello World!";

    constructor(private router: Router) {}

    onCallback(event) {
        console.log(event);
        this.router.navigate(['example-two']);
    }
}

组件做他们应该做的事情。

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

@Component({
    selector: "component-one",
    templateUrl: "./component-one.html",
    styleUrls: ["./component-one.scss"],
    encapsulation: ViewEncapsulation.Emulated,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ComponentOne implements OnInit {
    @Input() variable: string;
    @Output() callback = new EventEmitter<any>();

    constructor() {}

    ngOnInit() {
        console.log("Variable: ", this.variable);
    }

    someRandomButtonClicked() {
        callback.emit({ data: "Callback Called" });
    }
}

现在,当我启动主应用程序时,一切都按预期显示,回调工作正常,但变量未定义。 我的 webcomponents 中的 @Input 声明中是否缺少某些内容?

【问题讨论】:

  • 您在all browsers 中看到相同的行为吗?在 Chrome 和 Firefox 中是一样的吗?
  • 在 Opera、Firefox 和 IE 上相同,不支持 customElements。

标签: angular custom-element angular-elements


【解决方案1】:

由于您使用的是角度元素,因此请确保您的变量名称在 smallcaps 中,如下所示 @Input() myvariable: string 而不是 @Input() myVariable: string 在这里检查 https://github.com/angular/angular/issues/24871

【讨论】:

  • 虽然理论上可以回答这个问题,但最好在此处包含答案的基本部分,并提供链接以供参考。
  • 这是给我的。
【解决方案2】:

我想你只是错过了理解新语法:)

当你在输入名称周围使用 [] 时,你告诉 Angular 你给了他一个变量。如果您不使用它,您可以要求 Angular 将其作为原始类型。

所以:

<component-one [variable]="myVar"   

必须在组件中定义一个名为“myVar”的变量

没有

<component-one variable="myVar" 

Angular 会将“myVar”作为字符串值

无用但有效:

<component-one [variable]="'myVar'"

你给一个新的字符串作为变量

【讨论】:

  • 我的错,我在写我的问题时犯了一个错误,我试图将名为 toPass 的变量传递给组件一,我相应地编辑了我的问题。
  • 它仍然无法使用新示例?你的组件是用@Component 注释的,对吗?
  • 不,它不起作用。事实上,当我使用具有硬编码值的属性(如 variable="Hello world" 但 [variable]="toPass" 和 variable="{{ toPass }}" 都不起作用)时,它正在工作。
  • 这没有任何意义。如果您在模板中的
  • 你的组件是用@Component 注释的吧?
【解决方案3】:

您可以在 ComponentOne 中启动变量。然后它应该工作

@Input() variable:String = “”;

【讨论】:

  • 在目标组件中实例化变量只需将日志更改为“变量:”字符串保持为空。
  • 是的,它只是删除了未定义的错误。我认为 xrobert 是正确的。 :)
【解决方案4】:

我认为这就是这里的解释:https://github.com/angular/angular/issues/29050。如果你 console.log() 你在 ngOnChanges() 钩子中的变量你会得到正确的值,但在 ngOnInit() 中它们仍然是未定义的。使用自定义元素时,挂钩的执行顺序会发生变化。这就是为什么在你的它是未定义的。就我而言,我仍在寻找如何强制 ngOnChanges() 先运行然后再运行 ngOnInit() 但还没有运气。

【讨论】:

    【解决方案5】:

    我遇到这个问题大约两天了,终于找到了解决方案。

    您需要做的是在您的子组件(Web 组件,您要公开)中使用方法 ngOnChanges()。因为这是为了检测您的 @Input() 字段的任何变化。

    这里我留下了我的网络组件的sn-p代码:

    @Component({
      selector: 'app-shipment-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    export class AppComponent implements OnInit, OnChanges {
    
      @Input() domain;
    
      @Output() response = new EventEmitter<string>();
    
      constructor() {
      }
    
      ngOnInit(): void {
      }
    
      ngOnChanges(changes: SimpleChanges): void {
        if (changes.domain) {
          console.log("Domain URL: ", this.domain);  
          this.response.emit(this.domain);
        }
      }
    
    }
    

    【讨论】:

      【解决方案6】:
      • 就我而言,当我将输入变量发送到自定义元素/Web 组件时,根本没有调用 ngOnChanges。所以我尝试了“属性绑定”,效果很好。

      来自 angular.io:
      Angular 中的属性绑定可帮助您设置属性值 直接地。属性绑定语法类似于属性绑定,但 而不是括号之间的元素属性,您在名称之前 带有前缀 attr 的属性,后跟一个点

      更改以下实现

      <custom-element name="{{userName}}"></custom-element>
      
                                   (or)
      
      <custom-element [name]="userName"></custom-element>
      

      到这里:

      <custom-element [attr.name]="userName"></custom-element>
      

      对于传递常量值,使用

      <custom-element [attr.name]="'John'"></custom-element>
      

      注意:您将在 ngOnChanges() 方法中获取值。

      【讨论】:

        【解决方案7】:

        在您的代码中,将问题中显示的所有位置的String 更改为string。看看它是否有效。

        Stringstring 类型的构造函数。更多信息here

        distinction between string and String

        更新:

        我有一种感觉,这与您使用的内联模板格式有关。

        改变这个

        @Component({
            selector: 'example',
            template: '<component-one [variable]="toPass" (callback)="onCallback($event)"></component-one>',
            styles: []
        })
        

        到这里,

        @Component({
            selector: 'example',
            template: `<component-one [variable]="toPass" (callback)="onCallback($event)"></component-one>`,
            styles: []
        })
        

        看,我把template: ''改成了这个

        template: ``
        

        否则,内联模板字符串的解析可能会搞砸。

        看看这是否有效。

        【讨论】:

        • 不,不会改变任何东西。
        • 也尝试了反引号模板,没有任何改变。
        • 你能重现这个问题吗?
        • 不容易,这些是Web组件,并且component-one被捆绑然后作为脚本从同一个域中导入。
        • @Romain 如果没有,将很难调试问题。在任何情况下,如果您在内联 template: 属性的值中使用 "',您应该恢复使用反引号 (`) 来包装整个字符串,或者将单个“有效”字符串部分作为数组。
        猜你喜欢
        • 2021-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-06
        • 2018-11-16
        • 1970-01-01
        • 2016-06-30
        • 1970-01-01
        相关资源
        最近更新 更多