Search code examples
javascriptangulartypescriptlazy-loadingplupload

Angular2 with Typescript, how to use Plupload CDN script file in lazy-loaded module?


I would like to use Plupload in an Angular2 component and access the Plupload JavaScript file from a CDN. I want it specific to a component so that it is not downloaded if it is not required - I want it to be in a lazy loaded module. How can I do this?

Now fully answered on this page!

The result of this quest, which included offering and awarding bounties to two people who worked hard with me on it, is as follows:

  1. Example of using Plupload with Angular 2 and TypeScript
  2. How to Lazy load a script from a CDN in Angular 2
  3. Example of how to use Plupload in a lazy loaded module
  4. How to use a lazy loaded script in Angular 2

    (See edit history for the ugly details that used to make up this question.)


Solution

  • Here's the overview of what you need to do to create a lazy-loaded Plupload feature while loading Plupload from a CDN:

    1. When the feature is needed (e.g. user clicks a button or visits a page), dynamically add a <script> tag to the page to load the Plupload library from a CDN.
    2. Wait until the library is loaded to proceed (or you could get a "plupload is undefined" error).
    3. Display the UI to interact with Plupload in one of your Angular templates. In its simplest form, this UI consists of two buttons: "Select files" and "Upload files".
    4. Initialize Plupload and wire it up to the UI.

    Complete, working code: https://plnkr.co/edit/4t39Rod4YNAOrHmZdxqc?p=preview

    Please take note of the following points in my implementation:

    • Regarding #2. A better way to check whether Plupload has finished loading would be to poll the global namespace for the existence of the plupload variable. As long as window.plupload does not exist, it means the library hasn't been loaded yet and that we should NOT proceed. For simplicity my code just waits for one second and proceeds.
    • Number 4 can prove a bit tricky. Plupload makes a heavy use of direct DOM access to wire its API to the HTML (e.g. document.getElementById('filelist')). This is something Angular discourages and that you should try avoiding whenever possible. More specifically direct DOM access is used in the following places:
      • To tell Plupload which DOM element should trigger the "Select files" dialog (what they call the browse_button config option). For this I could not avoid the direct DOM reference and I used the @ViewChild decorator to get a hold of the "Select Files" button.
      • To display selected files in the template. For this I converted the Plupload syntax into the regular Angular syntax. I push selected files to a class property called fileList which I display in the template using a standard *ngFor.
      • The "Upload Files" button triggers some code that does the actual uploading and refreshes the UI to show upload progress. Once more, I converted this to regular Angular syntax using event binding and data binding.

    Let me know if you have any questions.