jibon57 / nativescript-mediafilepicker

A complete file picker solution for NativeScript
Apache License 2.0
51 stars 39 forks source link

NgOnChanges doesn't trigger when I change the input value within the getFiles event handler #108

Closed csimpi closed 4 years ago

csimpi commented 4 years ago

Describe the bug A clear and concise description of what the bug is.

I have an Angular component, with Input [src]. Src accepts a path of a local file. ngOnChanges should be triggered when I change the value of [src] but it doesn't trigger anything, just hangs so I can't show up the selected image.

    this.mediafilepicker.on("getFiles", res=> {
      let results = res.object.get('results');
      console.dir('getFiles',results);
      let session = bghttp.session("image-upload");
      this.selectedImage = results[0].file;
    });

<mtp-img [src]="selectedImage"></mtp-img>

This is the corresponding ngOnChanges function that should be triggered when I set this.selectedImage, but it does nothing some reason:

  ngOnChanges(changes: SimpleChanges) {
    console.log('ngOnChanges');
    this.loadImg();
  }

To Reproduce Steps to reproduce the behavior:

Expected behavior A clear and concise description of what you expected to happen.

ngOnChanges should be triggered. I've even tried to put this.selectedImage = results[0].file; to a setTimeout() function doesn't help.

NativeScript Info(please run tns info): √ Getting NativeScript components versions information... √ Component nativescript has 6.5.0 version and is up to date. √ Component tns-core-modules has 6.5.1 version and is up to date. √ Component tns-android has 6.5.1 version and is up to date. × Component tns-ios is not installed.

Sample Code(please provide minimum code to reproduce problem): above

Additional context Add any other context about the problem here.

Sometimes it works ... there's no explanation, I restart the app and 1/5 times the ngOnChange is triggered as expected some reason.. a real mistery

jibon57 commented 4 years ago

You are referencing this in a wrong way. Possible way:

let t = this;
    this.mediafilepicker.on("getFiles", res=> {
      let results = res.object.get('results');
      console.dir('getFiles',results);
      let session = bghttp.session("image-upload");
      t.selectedImage = results[0].file;
    });
csimpi commented 4 years ago

More UPDATE: If I click to somewhere else everything appears the excepted way... I don't know why the View requires a user interaction to be re-rendered, but I'm sure this is not about the this reference..

csimpi commented 4 years ago

Some reason this plugin's event callbacks are outside of ngZone, even if I use the TypeScript format to declare the callback function (so inside of the function should be within the ngZone).

I'm sure there'll be other devs in the same situation, so until the maintainer is not fixing this issue, here's the workaround:

constructor(private ngZone: NgZone ) { }
testVariable: string;

ngOnInit() {
   this.testVariable = 'foo';

   this.someService.someObservable.subscribe(
      () => console.log('success'),
      (error) => console.log('error', error),
      () => {
      this.ngZone.run( () => {
         this.testVariable += '-bar';
      });
      }
   );
}

Source: https://stackoverflow.com/questions/50519200/angular-6-view-is-not-updated-after-changing-a-variable-within-subscribe

This is the updated code with the original this reference, so it's clear now your solution is wrong this has been referenced the right way, I had to add only ngZone.run()

      this.mediafilepicker.on("getFiles", res=> {
        let results = res.object.get('results');
        console.dir('getFiles',results);

        this.ngZone.run( () => {
          this.selectedImage = results[0].file;
        });

Nothing else has helped. A setter/getter or SetTimeout won't help. Changing this reference won't help either.

meljunediaz commented 4 years ago

NgZone solved the issue.