1

I am trying to add Html by targeting an id. Html is showing but ngModel and click are not working. How can I make it work?

app.component.html

<div id="myid">

</div>

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {

   mytext = "add something"
   constructor(private myElement: ElementRef) {}
   ngOnInit() {
    this.addDiv()
  }
  pop(){
   alert("hello")
  }
  addDiv(){
    var div = document.createElement('div');
    div.innerHTML = `<div>
          <input type="text" [(ngModel)]="mytext">
           <button type="button" class="btn (click)="pop()">Basic</button>
        </div>`;
    this.myElement.nativeElement.querySelector('#myid').append(div)
  }
}
  • 3
    This is bad practice. You should avoid using elementRef to manipulate the DOM. See [ElementRef](https://angular.io/api/core/ElementRef) – CornelC Apr 27 '18 at 08:32

2 Answers2

0

CornelC is correct in stating this is bad practice. In the past I have used reactive forms and form arrays. There is an answer here that provides detail into setting up a reactive form with a form array:

How to dynamically add and remove form fields in Angular 2

As an aside: you have not closed your class attribute with a closing quote and you need to close the template string with a closing `:

div.innerHTML = `<div>
      <input type="text" [(ngModel)]="mytext">
       <button type="button" class="btn (click)="pop()">Basic</button>
    </div>;

Change to:

div.innerHTML = `<div>
      <input type="text" [(ngModel)]="mytext">
       <button type="button" class="btn" (click)="pop()">Basic</button>
    </div>;`
Pete
  • 769
  • 7
  • 20
  • 1
    I didn't down vote your answer, but I think that your solution will not work, because angular bindings will not work when you change the DOM like that. Your observations about the quotes are correct though. – CornelC Apr 27 '18 at 08:41
0

You cannot use angular specific template syntax if you create the html on the fly and set it via innerHTML. All angular templates are compiled during build time. Angular specific things like (click)="..."" will simply not work.

Anyways, as others have stated you should not be manipulating your html directly when working with angular.

Create your component like this:

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

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
    // This field will control the visibility of your section
    isDivVisible = false;
    mytext = 'add something';
    constructor(private myElement: ElementRef) { }
    ngOnInit() {
        this.isDivVisible = true;
    }
    pop() {
        alert('hello');
    }
}

Instead of manually creating the dom element, we simply want to use the isDivVisible variable to control the visibility of the div.

In your template do something like this:

<div *ngIf="isDivVisible">
    <input type="text" [(ngModel)]="mytext">
    <button type="button" class="btn" (click)="pop()">Basic</button>
</div>

The div with *ngIf directive will only be visible when you set the isDivVisible variable to true. You can easily hide it again by setting isDivVisible to false.

Short note: If you use the ngOnInit method your component should also be implementing the OnInit interface.

tom van green
  • 1,674
  • 10
  • 14
  • This is required to add (click) function like this in my case – Chaitanya Thakre Apr 27 '18 at 10:26
  • Yes, if you want to use the (click) function, you need to have the (click) part in your template. You cannot use it in innerHTML. Just to make sure. The html code I've written in my example is in the app.component.html. – tom van green Apr 27 '18 at 10:47