TransWikia.com

LWC: Issue with loading static resources

Salesforce Asked on November 30, 2021

I’ve incorporated the code documented in the following article into a new component:

Play YouTube Videos Through Lightning Web Components

It seems like the two JS files referenced, iframe_api.js and widgetapi.js, don’t always load when the component is first loaded. In other words, initially the embedded YouTube player craps out the very first time I load the component. Afterwards, the resources load fine. This is true even when I clear my Chrome cache–which seems odd to me since this would force my browser client to refetch the static resource from the org.

I thought that the use of the Promise.all() to encapsulate the two loadScript() calls would ensure that both JS resources are loaded before continuing, but in my experience, that is not the case.

renderedCallback() {
        .
        .
        .
        if (window.YT) {
            if (this.player) {
                this.player.cueVideoById(this.youTubeId);
            } else {
                this.onYouTubeIframeAPIReady();
            }
        } else {
            Promise.all([
                loadScript(this, YouTubePath + '/iframe_api.js'),
                loadScript(this, YouTubePath + '/widgetapi.js')
            ])
                .then(() => {
                    this.onYouTubeIframeAPIReady();
                })
                .catch(error => {
                    console.log('Error with loading the YouTube static resources');
                    console.log(JSON.stringify(error));
                    this.showErrorToast(error);
                });
        }
    }

I’ve tried splitting the two JS files into their own individual static resources, but the same problem happens.

Is there another way I can address this issue?

One Answer

I'm not entirely sure why that method shouldn't work, but in your specific case, this playground should provide you with what you need. It's a component that plays YouTube videos given an ID.

Here's the relevant code:

import { LightningElement, api } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { YT as YoutubePath1 } from './YouTubeJS/iframe_api.js';
import { YT as YouTubePath2 } from './YouTubeJS/widget_api.js';

export default class BasicYouTubePlayer extends LightningElement {
    @api youTubeId;
    player;

    renderedCallback() {
        if (!this.youTubeId) {
            return;
        }

        if (window.YT) {
            if (this.player) {
                this.player.cueVideoById(this.youTubeId);
            } else {
                this.onYouTubeIframeAPIReady();
            }
        } else {
            Promise.all([
                loadScript(this, YouTubePath1),
                loadScript(this, YouTubePath2)
            ])
                .then(() => {
                    this.onYouTubeIframeAPIReady();
                })
                .catch(error => {
                    this.showErrorToast(error);
                });
        }
    }

    onPlayerError(e) {
        let explanation = '';
        if (e.data === 2) {
            explanation = 'Invalid YouTube ID';
        } else if (e.data === 5) {
            explanation =
                'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.';
        } else if (e.data === 100) {
            explanation =
                'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.';
        } else if (e.data === 101 || e.data === 150) {
            explanation =
                'The owner of the requested video does not allow it to be played in embedded players.';
        }

        this.showErrorToast(explanation);
    }

    showErrorToast(explanation) {
        const evt = new ShowToastEvent({
            title: 'Error loading YouTube player',
            message: explanation,
            variant: 'error'
        });
        this.dispatchEvent(evt);
    }

    onYouTubeIframeAPIReady() {
        const containerElem = this.template.querySelector('.wrapper');
        const playerElem = document.createElement('DIV');
        playerElem.className = 'player';
        containerElem.appendChild(playerElem);

        this.player = new window.YT.Player(playerElem, {
            height: '390',
            width: '100%',
            videoId: this.youTubeId,
            events: {
                onError: this.onPlayerError.bind(this)
            }
        });
    }
}

<template>
    <template if:true={youTubeId}>
        <div class="wrapper" lwc:dom="manual"></div>
    </template>
    <template if:false={youTubeId}>
        <lightning-card  title="Empty YouTube ID found. Please specify a YouTube ID."></lightning-card>
    </template>
</template>

Note: the two imported files need to be modified to support importing. Add the following lines to the end of each file, as noted here:

const YT1 = window.YT;
export { YT1 as YT };

Answered by sfdcfox on November 30, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP