Angular 2 - selectpicker and datatables not initialising properly after switching routes

701 views Asked by At

So here's what my page looks like when you first load it. enter image description here

After switching, it looks like this. enter image description here

This is code for this weirdly broken part:

ngOnInit(): void 
{   
    $(document).ready(function() {
        (<any>$("#the_table")).DataTable();
        (<any>$('#selectpicker')).selectpicker();   
    }   
    if ($.isEmptyObject(this.route.snapshot.params) === false)
    {   
        this.id = +(<any>this.route.snapshot.params).id;
    }   
    let pass = {type: "reports"};
    this.searchService.searchHttp( {type: "reports"} ).then( (response: any) =>  
        {   
            this.reports = response;
            console.log(response);
        }); 
}  

Here's code for the 'search' which isn't broken.

ngOnInit(): void 
{   
    $(document).ready(function() {
           (<any>$('.selectpicker')).selectpicker();
    }); 

    this.tags = this.searchService.get_tags();
    this.draw_table();
}  

draw_table()
{
    let json = JSON.stringify(this.tags);
    this.table = (<any>$("#ajax_table")).DataTable({
        "dom": 'Bfrtip',
        "processing": true,
        "ajax": {
            "url": "app/php/search.php" + "?json=" + encodeURIComponent(json) + "&type=search",
        },
        "columns": [
            { "data": "id" },
            { "data": "ref" },
            { "data": "date" },
            { "data": "title" },
            { "data": "site" },
            { "data": "location" }
        ],
        "filter": true,
        "select": true,
        "autoWidth": false,
        "buttons": [
            {
                "text": "test",
                action: () =>
                {
                    console.log(table.rows( { selected: true } ).data());
                    let data = table.rows( { selected: true } ).data()[0];
                    data = (data) ? data : null;
                    this.router.navigate(['/main', data ]);
                },
                enabled: false
            }
        ],
        //"destroy": true
    });

    let table = this.table;

    table.on( 'select', function () {
        table.button(0).enable(true);
    } );
    table.on( 'deselect', function () {
        table.button(0).enable(false);
    });
}

If anyone has any idea, feel free to point it out.

Update Tried NgZone:

ngOnInit(): void 
{   
    if ($.isEmptyObject(this.route.snapshot.params) === false)
    {   
        this.id = +(<any>this.route.snapshot.params).id;
    }   
    let pass = {type: "reports"};
    this.searchService.searchHttp( {type: "reports"} ).then( (response: any) =>  
        {   
            this.reports = response;
            console.log(response);
            this.ngZone.onStable.first().subscribe( () => { 
                (<any>$('#selectpicker')).selectpicker();
                (<any>$("#the_table")).DataTable();
            }); 
        }); 
} 
2

There are 2 answers

1
Ankush Jain On

There are few points you need to take care of.

First using document.ready in angular2 is insulting angular2. Remove it.

and secondly to know How to use jQuery plugin in angular2, you need to first fetch data from http service and assign it to member variable to bind it on the page. And then you should subscribe to onStable event which ensures that all data binding has been completed and data has been rendered on the page.

onStable event will be fired only once.

    constructor(private ngZone: NgZone) {}

    ngOnInit() {
        this.searchService.searchHttp( {type: "reports"} ).then( (response: any) =>  
                {   
                   this.reports = response;
                   // waiting until select options are rendered
                   this.ngZone.onStable.first().subscribe(() => {
                      $('#selectpicker')).selectpicker(); 
                   });
                });
            }
    }

onStable : EventEmitter: Notifies when the last onMicrotaskEmpty has run and there are no more microtasks, which implies we are about to relinquish VM turn. This event gets called just once.

0
A. L On

Solved it by using public ngAfterViewChecked(): void {} instead.