1

In my Angular app, I'm attempting to have images, pdfs, and other various download links open in a new tab when clicked on in mobile. This is working as expected on a desktop, but mobile keeps opening the download in the current window, and forcing the user to use the browser back button.

  <span class="link" (click)="viewFile(document.docID)">{{document.comments}}/span>


  viewFile(documentName: string){
    this.spinner.show();
    this.formService.viewFile(documentName).subscribe((data: any) => {
      this.spinner.hide();
      const link = document.createElement('a');
      link.href = window.URL.createObjectURL(data);
      link.target = '_blank';
      link.click();
    }, (error) => {
      this.spinner.hide();
      this.toastr.error(error);
    });
  }

I have also tried window.open(link.href, '_blank') with no success

How can I modify my viewFile function in order to force the download to open in a new tab in mobile?

I am serving my app and the download content over https. Mixed content is not the issue.

Capo
  • 216
  • 3
  • 10

2 Answers2

0

Why not simply use anchor instead and explicitly instruct browser to open a new page?

<span> 
   <a [href]="getFileLink(document.docID)" target="_blank">
      {{document.comments}}
   </a>
</span>
tgralex
  • 794
  • 4
  • 14
  • These links are built and returned via the api. Clicking the link will be passing a null href since the call won't have returned. Is there a way to make these async that I'm not aware of? – Capo Aug 26 '19 at 20:17
  • This will work only if API could be changed to return URLs along with data. – tgralex Aug 26 '19 at 20:58
  • Alternatively you can download URLs on background thread and update missing URLs. But not sure if it will be a good solution if there are many anchors to be resolved... – tgralex Aug 26 '19 at 21:00
0

It turns out this was a result of the native popup blocker firing since the user action was too far removed from the new window opening. To get around this, I create the window object on click and then reassign it once the callback has returned.

 viewFile(docID: string, isLocalDoc) {
    const newWindow = window.open(this.formService.setLoadingUrl());
    // timeout put in place b/c it returns too quickly for the new window without it (results in the window closing early)
    setTimeout(() => {
      this.spinner.show();
      this.formService.viewFile(docID, isLocalDoc).subscribe((data: any) => {
        this.spinner.hide();
        setTimeout(() => {
          newWindow.location.href = window.URL.createObjectURL(data);
          if (data.type === 'application/octet-stream') {
            newWindow.close();
          }
        }, 500);
      }, (error) => {
        this.spinner.hide();
        newWindow.close();
        this.toastr.error(error);
      });
    }, 500);
  }
Capo
  • 216
  • 3
  • 10