Angular - FileReader() dont get any path

1.9k views Asked by At

I try to pass an Image in an dialog where the User can crop the image via cropperjs and can upload it afterwards but sometimes the FileReader() didnt get any path.

It is strange, sometimes it works but most of the time my variable is empty... i think did is random because i dont find a pattern to get the URL.

This component.ts

  constructor(private route: ActivatedRoute, public dialog: MatDialog,) { }
  @Input() user: any
  @Input() userProfile: any
  @Input() userPosts: any
  imageSource: any = null;

  ngOnInit(): void {
    this.route.data.subscribe((data: {user: any}) => { this.user = data.user;});
    this.route.data.subscribe((data: {userProfile: any}) => { this.userProfile = data.userProfile;});
    this.route.data.subscribe((data: {userPosts: any}) => { this.userPosts = data.userPosts;});
    console.log(this.userProfile)
  }

  openDialog(src:string): void {
    const dialogRef = this.dialog.open(UserImgDialogComponent, {
      width: '500px',
      minHeight: '350px',
      data: src,
    });

    dialogRef.afterClosed().subscribe(result => {
      if(result) {
        console.log('Yes')
      }
    })
  }

  uploadFile($event) {

    if ($event.target.files && $event.target.files[0]) {
      const file = $event.target.files[0];

      const reader = new FileReader();
      reader.readAsDataURL(file)
      reader.onload = e => this.imageSource = reader.result;
      this.openDialog(this.imageSource);
    }
}

}

This is my html

 <div class="UserImageDiv">
        <img [src]="userProfile.profileImagePath" class="UserImage">
        <button mat-icon-button matTooltip="Profilbild ändern" class='changeUserImg' (click)="uploader.click()">
          <mat-icon>add_a_photo</mat-icon>
        </button>
        <input hidden type="file" #uploader (change)="uploadFile($event)" />
      </div>

Can someone please help me? Is there another way to get the Path of an Image upload?

1

There are 1 answers

0
Michael D On BEST ANSWER

I see multiple issues here.

  1. You don't need 3 individual subscriptions to route. You could assign all the properties within a single subscription
ngOnInit(): void {
  this.route.data.subscribe((data: any) => {
    this.user = data.user;
    this.userProfile = data.userProfile;
    this.userPosts = data.userPosts;
    
    console.log(this.userProfile); // <-- should be inside the subscription
  });
}
  1. Additionally, the console.log(this.userProfile) should be inside the subscription. The variable is assigned asynchronously and might not be assigned any values yet if it's outside the subscription.

  2. The issue with image is the same. The variable this.imageSource is assigned async inside the onload callback. So the call this.openDialog should be inside the callback.

uploadFile($event) {
  if ($event.target.files && $event.target.files[0]) {
    const file = $event.target.files[0];
    const reader = new FileReader();
    reader.readAsDataURL(file)
    reader.onload = (e: any) => {
      this.imageSource = reader.result;
      this.openDialog(this.imageSource); // <-- should be inside the callback
    }
  }
}

You could learn more about asynchronous data here.

Also the concept of pure/impure pipes are related to Angular pipes and it doesn't apply to you seeing that you aren't using any Angular pipe in the template. If you're new to Angular, I'd recommend you to go through their tutorial. It introduces some of the basics.