Search code examples
jqueryangularangular4-forms

(click) event not working while append any data in ANGULAR 4


while i am trying to append the "tr tag" (click) event was not working in angular 4, here is my Code.

$('#time_table_table tbody').append('<tr data-id="1"><td>Sunday<a (click)="assign(1)">Assign</a></td></tr>');

when i am trying to "console.log(id)" in "assign()" function it will not call.


Solution

  • if i am use click Event then can i get it's value in Component in "assign(id)" function?

    You should be able to do that. Grab your table with @ViewChild (as I wrote bellow), but before, set template variable - <table #myTable... , @ViewChild('myTable') myTable:ElementRef;, then create needed elements through Renderer - let tr1 = this.rd.createElement("tr"); , let td1 = this.rd.createElement("td"); , let link1 = this.rd.createElement("a"); , create text nodes with createText method, append them to corresponding HTML nodes with appendChild and add click handler with listen() method - this.rd.listen(link1, 'click', function(event.target)). event.target will return the reference to the link1 node. So you could travel up in the HTML tree with parentElement property or similar and get the id. You should also be able to pass the parent directly from click handler, like function(event.target.parentElement)


    If you want to create a whole new table and append it, the logic is the same:

    // Create header row and append to table:
    let table = this.rd.createElement("table");  
    let tr1 = this.rd.createElement("tr");  
    let tr1Th1 = this.rd.createElement("th");  
    let tr1Text = this.rd.createText("Name")
    this.rd.appendChild(table, tr1);
    this.rd.appendChild(tr1, tr1Th1);
    this.rd.appendChild(tr1Th1, tr1Text);
    
    // add body row:
    let tr2 = this.rd.createElement("tr");  
    let tr2Td1 = this.rd.createElement("td");  
    let tr2Text = this.rd.createText("John")
    this.rd.appendChild(table, tr2);
    this.rd.appendChild(tr2, tr2Td1);
    this.rd.appendChild(tr2Td1, tr2Text);
    

    Looks a bit ugly, but if you do it from your ComponentClass, I dont know other ways. And after that with @ViewChild grab your parent element and append that table to it. Add attributes with setAttribute method. To improve code you can use some loops or functional programming techniques.


    Angular is not designed to work directly with DOM, so jQuery is a bad choice. In Angular, at these days, we use Renderer2.

    Now in your issue, you first need to grab a reference of your #time_table_table tbody element. First thought might be to simply use the ElementRef:

    constructor(el: ElementRef) {
      el.nativeElement.querySelector('#time_table_table tbody');
    }
    

    But you shouldn't use ElementRef to modify the DOM. For such task you can use @ViewChild(). It accepts a string parameter which is a name of your template variable. So @ViewChild('myDiv') el:ElementRef query would refer to <div #myDiv> Foo </div>.

    Here is an example how you can do it:

    import {ElementRef, Renderer2, ViewChild  } from '@angular/core';
    
    export class MyComponent implements OnInit {
      @ViewChild('yourVariable') el:ElementRef;
    
    constructor(private rd: Renderer2){
    
    ngOnInit() {   
      let btn = this.rd.createElement("button");  
      let text = this.rd.createText("Click")
      this.rd.appendChild(btn, text);
      this.rd.appendChild(this.el.nativeElement, btn)
    
      this.rd.listen(btn, "click", () => console.log(1));
    }
    

    You read about Renderer2 to learn more about its methods and properties.