How do I get @vimeo/player to work on my Angular2/Typescript project (specifically Ionic2) ?
Trying to get the vimeo player to work with Angular2/Typescript.
npm install --save @vimeo/player
According to their documentation the library can be used like so:
If you’re using a module bundler like webpack or rollup, the exported object will be the Player constructor (unlike the browser where it is attached to window.Vimeo):
import Player from '@vimeo/player';
const player = new Player('handstick', {
id: 19231868,
width: 640
});
player.on('play', function() {
console.log('played the video!');
});
Which looks super promising ! But doesn't work.
I've installed @vimeo/player
and @types/vimeo__player
I created a player component in my Ionic2 app.
player.ts:
import {Component, ViewChild} from '@angular/core';
import {NavController} from "ionic-angular/index";
//noinspection TypeScriptCheckImport,TypeScriptCheckImport
import Player from "@vimeo/player";
@Component({
selector: 'player-component',
templateUrl: 'player.html'
})
export class PlayerComponent {
@ViewChild('player_container') playerContainer;
private player: Player;
constructor(public navCtrl: NavController){}
ngAfterViewInit() {
// child is set
this.player = new Player(this.playerContainer);
console.log(Player);
}
}
I use view child, but I've also tried with the element's ID.
player.html
<div #player_container></div>
And get the following error:
Uncaught (in promise): TypeError: You must pass either a valid element or a valid id. Player@http://localhost:8100/build/main.js:102846:32 ngAfterViewInit@http://localhost:8100/build/main.js:74715:80 callProviderLifecycles@http://localhost:8100/build/main.js:11417:33 callElementProvidersLifecycles@http://localhost:8100/build/main.js:11392:35 callLifecycleHooksChildrenFirst@http://localhost:8100/build/main.js:11376:47 checkAndUpdateView@http://localhost:8100/build/main.js:12408:36 callWithDebugContext@http://localhost:8100/build/main.js:13462:47 detectChanges@http://localhost:8100/build/main.js:10474:81 _viewAttachToDOM@http://localhost:8100/build/main.js:43884:53 _transition@http://localhost:8100/build/main.js:43976:34 onInvoke@http://localhost:8100/build/main.js:4406:43 run@http://localhost:8100/build/polyfills.js:3:4146 http://localhost:8100/build/polyfills.js:3:13734 onInvokeTask@http://localhost:8100/build/main.js:4397:47 runTask@http://localhost:8100/build/polyfills.js:3:4841 o@http://localhost:8100/build/polyfills.js:3:1898 invoke@http://localhost:8100/build/polyfills.js:3:10674
As you can see it compiles but crashes at runtime.
@types/vimeo__player Just doesn't seem to be finished, and doesn't even seem to be noticed when I import @vimeo/player
The issue on github regarding vimeo__player seems show that this is true.
It looks like module resolution is correctly resolving it as a JS module, but only because it didn't find the types first. Are you sure you've correctly included those types? --listFiles would show you if it's lincluded.
Issued opened on Vimeo's github player page.
Your problem is not caused by @types/vimeo__player
neither it is related to your build system/configuration.
TypeScript type definitions never, never, never affect runtime's behaviour. Even compile-time errors have no other effect than displaying red in the console, the JavaScript will still be emitted.
Looking at the stack trace you've got, we can also say that Player
is effectively imported, and since you're saying that there is no compile-time error, everything is good on the build aspect of the things.
In fact, the error says it all: TypeError: You must pass either a valid element or a valid id.
.
Player
says that it expects an HTMLElement
.
The problem is, you are using @ViewChild()
from Angular. This decorator will return a wrapper when you are querying on a native element. This wrapper is of type ElementRef
, and has a property named nativeElement
that contains the original, DOM element.
So instead of doing this:
this.player = new Player(this.playerContainer);
Do this:
this.player = new Player(this.playerContainer.nativeElement);
But you may now think "why TypeScript didn't produced a type error since I'm not passing a native element ?". That's a good question, I don't have enough data to be sure, but I think that your import may be incorrect.
Instead of:
//noinspection TypeScriptCheckImport,TypeScriptCheckImport
import Player from "@vimeo/player";
Can you try to do this?
import { Player } from '@vimeo/player';
Looking at the .d.ts file, it looks like that Player is a named export. But you're right, the type definitions of @vimeo/player are incomplete, or not in sync with the JavaScript library. You should be aware of that type of problems in TypeScript, although this does not happen everyday ;)
For a standard typescript project this import statement works.
import * as Player from "@vimeo/player/dist/player.js";
In case your ViewChild is undefined (due to a lazy load, etc), you can try this:
Code:
import { Component, ViewChildren } from '@angular/core';
import Player from "@vimeo/player";
@Component({
selector: 'player-component',
templateUrl: 'player.html'
})
export class PlayerComponent {
private player: Player;
@ViewChildren('player_container') playerContainer;
ngAfterViewInit() {
/* wait DOM be available */
this.playerContainer.changes.subscribe(item => {
if (this.playerContainer.length) {
/* DOM AVAILABLE */
this.player = new Player(this.playerContainer.first.nativeElement);
this.player.on('play', function() {
console.log('played the video!');
});
this.player.getVideoTitle().then(function(title) {
console.log('title:', title);
});
}
})
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With