How to create a fully dynamic button in angular 6?

Here you need to property binding and event binding like below.

app.component.html

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

app.component.ts

export class AppComponent  {
  name = 'Angular';

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

button.component.html

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

button.component.ts

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

@Component({
  selector: 'app-button',
  templateUrl: './button.component.html',
  styleUrls: ['./button.component.css'],
  encapsulation: ViewEncapsulation.None

})
export class ButtonComponent implements OnInit {

  @Input() group: FormGroup;
  @Input() type: string;
  @Input() description: string;
  @Input() class: string;
  @Input() data: string;
  @Output() callFunction = new EventEmitter();



  constructor() { }

  ngOnInit() {

    this.group = new FormGroup({
      firstName: new FormControl()
    });
  }


  onClick(event) {
    this.callFunction.emit('I am button');
  }


}

Here is solution on stackblitz


I was able to make this example work:

Child Component

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();
    }
  }
}

Parent Template

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

Notice that is it using property binding with [] and referencing the function in the parent's component code.

Parent Component

export class AppComponent  {
  name = 'Angular';

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

I have a working stackblitz here: https://stackblitz.com/edit/angular-function-input-property-deborahk

When you run the code you will see "called the function" in the console.

I have not used dynamically loaded components, so not sure how that impacts how this works. But wanted to provide the basic syntax that does work in a "normal" component.

UPDATE

Setting an @Input property like this:

@Input() callFunction: Function;

Cannot be bound like this:

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

Input properties are set using property binding:

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

If you want to use event binding, you'll need to define an @Output property.