1

I'm having a hard time trying to install video.js's Rangeslider plugin in Angular 13. The problem is that the rangeslider code expects a global videojs variable to be available and alters it's prototype.

So in this moment videojs is provided by an import in my component:

import videojs from 'video.js';

And I start videojs with this code in AfterViewInit:

this.player = videojs(this.myVideoComponent.nativeElement, this.config, () => {
    console.log('player ready!');
});

Now AFAIK Rangeslider plug in doesn't have a npm package available, so I download it and imported as a normal file within my project:

import RangeSlider from 'src/app/shared/rangeslider-videojs';

This created the error videojs not found, because videojs isn't global and not even initialized;

So to be able to have videojs initialized it has to be in AfterViewInit after the initialization code mentioned above. So I tried all this:

let RangeSlider = require('src/app/shared/rangeslider-videojs');

let RangeSlider = require('src/app/shared/rangeslider-videojs')(videojs, {});

this.player.bind(require('src/app/shared/rangeslider-videojs'));

window['videojs'] = require('src/app/shared/rangeslider-videojs');

With equal results. I CAN put videojs and rangeslider files directly in root dir and use <script> tags to load it the hard way. But that would be so ugly I'm very relutant in doing it.

Anyone knows a way to load rangeslider plugin on an Angular component ?

Edit

I tried @yurzui solution. I put the lazyload function in the same component file I use videojs, but outside the component code, I mean between the imports and @Component. I got the following error:

Property 'videojs' is missing in type 'typeof videojs' but required in type 'typeof import("/vagrant/frontend/node_modules/@types/video.js/index")'.

22  const videoJs: any = (window['videojs'] = (await import('video.js')).default);
                          ~~~~~~~~~~~~~~~~~

  node_modules/@types/video.js/index.d.ts:40:1
    40 export default videojs;
       ~~~~~~~~~~~~~~~~~~~~~~~
    'videojs' is declared here.
Nelson Teixeira
  • 6,297
  • 5
  • 36
  • 73

1 Answers1

1

You can assign videosjs default import to global window variable so that it will be visible inside plugin code.

Also, consider an option to lazy load those scripts dynamically. It will solve your issue and reduce the size of main bundle.

async function loadVideoJs() {
  const videoJs = (window['videojs'] = (await import('video.js')).default);
  await import('src/app/shared/rangeslider-videojs');
  return videoJs;
}

app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewInit {
  player: any;

  @ViewChild('myVideoComponent') myVideoComponent: ElementRef;

  async ngAfterViewInit() {
    const videoJS = await loadVideoJs();
    this.player = videoJS(this.myVideoComponent.nativeElement, {}, () => {
      console.log('player ready!');
    });
    this.player.rangeSlider({
      ...
    });
  }
}

You can play with it in this repo https://github.com/alexzuza/angular-cli-videojs

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • Thanks. Couple questions: 1-I tried to load it on a global variable but it didn't work besides using script tags. How would I do it ? 2-Where would I put that lazy load function ? In a lib and import it on the component or in the component itself ? – Nelson Teixeira Sep 12 '22 at 14:28
  • 1) Loading videojs within script tag could not work because script is being loaded asynchronously and at the time of plugin initialization global variable is not ready yet. 2) You can put it anywhere, even within the same file. – yurzui Sep 12 '22 at 14:44
  • I tried the lazy load function and got an error I didn't understood. Check my edit to the question plz. – Nelson Teixeira Sep 12 '22 at 15:14
  • I think, AFAIU that the videojs file already declares a videojs global variable and namespace and it's confliting with `window['videojs'] = <...>`. It's interesting, because if I use `import videojs from 'video.js';` in the component it doesn't add videojs as a global property to the window object. – Nelson Teixeira Sep 12 '22 at 15:41
  • It looks like your tsconfig has different `compilerOptions`. I added `typings.d.ts` file to solve it. Please check this repo for final solution https://github.com/alexzuza/angular-cli-videojs – yurzui Sep 12 '22 at 16:30
  • Yurzui, you saving me again! :) When I think I won't make it, there it comes: Yurzui to the rescue! :D You may not remember, but you helped me some time ago with a very difficult Keycloak problem I was banging my head on. Thanks man. It worked. The bounty is yours :) May you have many good things in your life. – Nelson Teixeira Sep 13 '22 at 02:57