Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 is not updating the UI when making changes to a variable/model in Node

I am currently using Angular 2 with Electron (which is basically using Node and web technologies to create a GUI).

All I want to do is list the files of the current directory.

Unfortunately, the variable "this.files" does not seem to update the data shown on the UI. Surprisingly however, when I click the dummy button thats linked to an empty method, it suddenly update. How do I fix this issue and whats the problem?

import {Component} from "@angular/core";
const fs = require('fs');

@Component(<any>{
    selector: 'files',
    template: `
<h2>Files</h2>

<ul *ngFor="let file of files">
    <li>{{ file }}</li>
</ul>

<button (click)="showFiles">Show Files</button>
`,
})
export class FilesComponent {
    files: any[];
    cwd: string;

    constructor() {}

    ngOnInit() {
        this.cwd = __dirname;
        this.files = [];
        this.loadFiles();
    }

    loadFiles() {
        fs.readdir(this.cwd, (err, dir) => {
            for (let filePath of dir) {
                console.log(filePath);
                this.files.push(filePath);
            }
        });
    }

    showFiles() {
        // Empty method
        // Shows the files for some reason despite nothing happening
    }
}
like image 429
Yahya Uddin Avatar asked Jun 30 '16 17:06

Yahya Uddin


2 Answers

That's probably caused by fs.readdir. It seems it is using an API that is not patched by Angulars zone. To work around you can use

export class FilesComponent {
   constructor(private cdRef:ChangeDetectorRef) {}

   loadFiles() {
     fs.readdir(this.cwd, (err, dir) => {
        for (let filePath of dir) {
            console.log(filePath);
            this.files.push(filePath);
        }
        this.cdRef.detectChanges();
     });
   }
}
like image 153
Günter Zöchbauer Avatar answered Oct 29 '22 13:10

Günter Zöchbauer


Here's another option for you as the accepted answer didn't work for my use case... basically fs runs outside of the Angular zone so you need to assign the variable inside of ngZone.

NOTE: You may not actually need to run change detection manually depending on your use case.

import {Component, NgZone, ChangeDetectorRef} from "@angular/core";
const fs = require('fs');

@Component(<any>{
    selector: 'files',
    template: `
<h2>Files</h2>

<ul *ngFor="let file of files">
    <li>{{ file }}</li>
</ul>

<button (click)="showFiles">Show Files</button>
`,
})
export class FilesComponent {
    files: any[];
    cwd: string;

    constructor(
      private cd: ChangeDetectorRef,
      private zone: NgZone
    ) {}

    ngOnInit() {
        this.cwd = __dirname;
        this.files = [];
        this.loadFiles();
    }

    loadFiles() {
        fs.readdir(this.cwd, (err, dir) => {
            var newFiles = [];
            for (let filePath of dir) {
                console.log(filePath);
                newfiles.push(filePath);
            }
            this.zone.run(() => {
              this.files = newFiles;
              // NOTE: you may be able to delete this next line depending on your use case
              this.cd.detectChanges();
            })
        });
    }

    showFiles() {
        // Empty method
        // Shows the files for some reason despite nothing happening
    }
}
like image 34
Kyle Krzeski Avatar answered Oct 29 '22 13:10

Kyle Krzeski