如何在角度6中创建全动态按钮?

时间:2019-02-25 06:04:19

标签: angular typescript

我正在为我的应用程序创建动态组件,这些组件可以在程序的各个部分中重复使用。到目前为止,我已经能够创建文本输入,并使用componentFactory将其动态添加和自定义为表单,并且它们可以完美地工作。

下一部分是创建完全动态的按钮,当将它们放置在目标视图中时可以对其进行自定义(就像带有表单的文本输入一样)。我试图使大多数事物通用,并且它们可以正常工作,但是我似乎遇到的问题是使(click)函数动态化。我也想添加需要使用componentFactory来触发的功能,但是由于某些原因,我无法这样做。

我找不到任何资源可以详细说明我遇到的这个特定问题。这是我到目前为止制作的组件:

button.component.ts

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

@Component({
  selector: 'app-button',
  templateUrl: './button.component.html',
  styleUrls: ['./button.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class ButtonComponent implements OnInit {

  @Input() group: FormGroup;
  @Input() type: string;
  @Input() description: string;
  @Input() class: string;
  @Input() data: string;
  @Input() callFunction: string;


  constructor() { }

  ngOnInit() {
  }

}

button.component.html

<div [formGroup]="group">
  <button type="{{ type }}" class="{{ class }}" (click)="{{callFunction}}">{{ description }}</button>
</div>

(click) button.component.html 中不起作用,它给我以下错误:

  

解析器错误:在需要表达式的地方进行插值({{}})

其他所有方法都可以,但是除非能够满足要求,否则我无法使按钮完全动态,并且我无法找到满足我要求的资源。

编辑:我添加了将组件导入视图的功能:

  buildLoginButton(){
    let data = {
      type: "button",
      class: "btn btn-primary px-4",
      description: this.translate.transform("pages[login_page][login_form][buttons][login]"),
      callFunction: "login()", //I have tried this.login() as well
      group: this.userForm
      }
    const inputFactory = this.resolver.resolveComponentFactory(ButtonComponent);
    const loginButton = this.login_button.createComponent(inputFactory);
    loginButton.instance.group = data.group;
    loginButton.instance.type = data.type;
    loginButton.instance.class = data.class;
    loginButton.instance.description = data.description;
    loginButton.instance.callFunction = data.callFunction;
  }

2 个答案:

答案 0 :(得分:2)

在这里,您需要进行如下所示的属性绑定和事件绑定。

app.component.html

  value;
  onKeyUp(e) {
    this.value = e.target.value.length;
  }

app.component.ts

<app-button description="Dyanmic Button" 
  class="button" (callFunction)="onButtonClicked($event)" >
</app-button>

button.component.html

export class AppComponent  {
  name = 'Angular';

  onButtonClicked(event) {
   console.log(event); // handle button clicked here.
  }
}

button.component.ts

<div [formGroup]="group">
  <button [type]="type" [class]="class" (click)="onClick($event)">
   {{ description }}
  </button>
</div>

Here is solution on stackblitz

答案 1 :(得分:2)

我能够使此示例生效:

子组件

export class HelloComponent implements OnChanges {
  @Input() name: string;
  @Input() callFunction: Function;  // NOTE: The data type here

  // Just some code to call the function
  ngOnChanges() {
    // Ensure the @Input property has been set before trying to call it.
    if (this.callFunction) {
      this.callFunction();
    }
  }
}

父模板

<hello 
  name="{{ name }}"
  [callFunction]="myCallBackFunction"></hello>

请注意,它是通过与[]进行属性绑定并在父级的组件代码中引用该函数来实现的。

父组件

export class AppComponent  {
  name = 'Angular';

  myCallBackFunction() {
    console.log('called the function')
  }
}

我这里有一个有效的堆叠闪电战:https://stackblitz.com/edit/angular-function-input-property-deborahk

运行代码时,您将在控制台中看到“称为函数”。

我还没有使用动态加载的组件,因此不确定如何影响它的工作方式。但是希望提供在“正常”组件中有效的基本语法。

更新

像这样设置@Input属性:

@Input() callFunction: Function;

不能这样绑定:

<button type="{{ type }}" class="{{ class }}" (click)="{{callFunction}}">

使用属性绑定设置输入属性:

<button type="{{ type }}" class="{{ class }}" [callFunction]="someFunction">

如果要使用事件绑定,则需要定义一个@Output属性。