<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zoaib</title>
    <description>The latest articles on DEV Community by Zoaib (@thisiszoaib).</description>
    <link>https://dev.to/thisiszoaib</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F428352%2F070a81f8-e8a7-4ee0-b139-daee2fc36b57.jpg</url>
      <title>DEV Community: Zoaib</title>
      <link>https://dev.to/thisiszoaib</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thisiszoaib"/>
    <language>en</language>
    <item>
      <title>Angular deferable views: Create a Lazy-loaded Youtube Player for a blog!</title>
      <dc:creator>Zoaib</dc:creator>
      <pubDate>Mon, 04 Mar 2024 14:07:10 +0000</pubDate>
      <link>https://dev.to/thisiszoaib/angular-deferable-views-create-a-lazy-loaded-youtube-player-for-a-blog-2hca</link>
      <guid>https://dev.to/thisiszoaib/angular-deferable-views-create-a-lazy-loaded-youtube-player-for-a-blog-2hca</guid>
      <description>&lt;p&gt;Interested in maximizing your Angular app's efficiency by learning how to lazy load components using the new Defer block in Angular v17? In this post, I'll walk you through the details of building a lazy-loaded video component and explore the various options available to trigger lazy loading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://youtu.be/cwWQFKPKcCw"&gt;https://youtu.be/cwWQFKPKcCw&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're more of a reader, check out the text tutorial below :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up The Project
&lt;/h2&gt;

&lt;p&gt;We'll be starting with an Angular version 17 project created through the updated CLI. To follow this tutorial, make sure you update your CLI using &lt;code&gt;ng update&lt;/code&gt; command or install it globally with the following command at the terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @angular/cli &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have also installed the latest Angular material package, version 17, and the &lt;a href="https://github.com/angular/components/tree/main/src/youtube-player#readme"&gt;YouTube Player package&lt;/a&gt;, an official Angular YouTube player module that gets regular updates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng add @angular/material
npm &lt;span class="nb"&gt;install&lt;/span&gt; @angular/youtube-player
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these all set up, let's dive into the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial Setup of Our Code
&lt;/h3&gt;

&lt;p&gt;I have put together a basic blog page, which is a common use case for the deferred video block. Creating a simple material toolbar titled "My Deferred blog" I made a container with a blog section, title, and some dummy text paragraphs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;mat-toolbar&lt;/span&gt; &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; My Deferred Blog! &lt;span class="nt"&gt;&amp;lt;/mat-toolbar&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"blog"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Angular v17 is released!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    ...dummy text paragraphs
  &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NSp_wrn6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/initial-layout.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NSp_wrn6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/initial-layout.png" alt="Initial blog layout" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I intend to insert a lazy-loaded YouTube video in between this text!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a New Component for Lazy Loading
&lt;/h2&gt;

&lt;p&gt;To create our video component used for lazy loading, we use the &lt;code&gt;ng generate component&lt;/code&gt; command to generate a new component, which we place inside of the components folder. We named this new component &lt;code&gt;VideoComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this video component, we remove the common module and import the YouTube player module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;YouTubePlayerModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/youtube-player&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;YouTubePlayerModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    ...
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: By default, Angular CLI v17 will create a &lt;code&gt;standalone&lt;/code&gt; app i.e. with standalone components generated automatically. Hence, you can see the flag in every component decorator, as above!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The rendered YouTube player requires the use of the Iframe API and an added script tag. I have created a service to perform this action in the YouTube service. This service loads and adds the script tag for the iframe API only once and enables a signal once the script has been added.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;YoutubeService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;apiLoaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apiLoaded&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// This code loads the IFrame Player API code asynchronously, according to the instructions at&lt;/span&gt;
      &lt;span class="c1"&gt;// https://developers.google.com/youtube/iframe_api_reference#Getting_Started&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.youtube.com/iframe_api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiLoaded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applying an if condition using the new control flow syntax, we know when the IFrame is entirely loaded and now we can add the youtube player to the template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    @if(apiLoaded()) {
    &amp;lt;youtube-player
      ...
    /&amp;gt;
    }
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;YoutubeVideoComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;apiLoaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;YoutubeService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;apiLoaded&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  YouTube Player Parameters
&lt;/h3&gt;

&lt;p&gt;The YouTube player takes width, height, and video ID parameters. Since we want to develop a &lt;strong&gt;reusable&lt;/strong&gt; component, we'll take the video ID as input. We will make video ID a requirement and add a definite assertion operator. Then, we will add an autoplay parameter within player variables, causing the video player to play automatically as soon as it loads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    @if(apiLoaded()) {
    &amp;lt;youtube-player
      [playerVars]="{ autoplay: 1 }"
      [width]="800"
      [height]="400"
      [videoId]="id"
    /&amp;gt;
    }
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;YoutubeVideoComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're ready to add the video component to the main blog, and we insert it after about four paragraphs in the text. We also need to add the video ID, which is one of my course introduction videos here (as an example).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"DzXMkLCAPRE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--APpv5-rW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/without-lazy-load.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--APpv5-rW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/without-lazy-load.png" alt="Video without lazy load" width="800" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we preview our blog, we notice the video loaded automatically without any lazy loading occurring. This means we haven't reduced our initial load time yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's add some lazy loading!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Leveraging Defer Block
&lt;/h2&gt;

&lt;p&gt;To achieve lazy loading, we can use Angular's new &lt;code&gt;defer&lt;/code&gt; block. By adding the &lt;code&gt;defer&lt;/code&gt; block to our video component, we create a lazy chunk file separate from the main bundle of the app. This single action reduces the initial load time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"DzXMkLCAPRE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B1RmvLeM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/lazy-chunk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B1RmvLeM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/lazy-chunk.png" alt="Our lazy chunk generated in the build terminal" width="751" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;defer&lt;/code&gt; without specifying a particular trigger, &lt;strong&gt;by default applies the 'on idle' trigger&lt;/strong&gt;. 'On idle' indicates that the chunk file loads only when the browser is idle after it has completed loading everything else on the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  The different defer triggers available
&lt;/h3&gt;

&lt;p&gt;Triggers we can specify on the Defer block includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On Viewport&lt;/li&gt;
&lt;li&gt;On Timer&lt;/li&gt;
&lt;li&gt;On Hover&lt;/li&gt;
&lt;li&gt;On Interaction&lt;/li&gt;
&lt;li&gt;Combinations of these.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  On Viewport trigger
&lt;/h3&gt;

&lt;p&gt;On Viewport is a useful &lt;code&gt;trigger&lt;/code&gt; that triggers lazy loading when the user scrolls to the specific component needing lazy loading. This tool functions with the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"&gt;Intersection Observer API&lt;/a&gt;. However, angular needs an element to add the intersection observer API to. Thus, we need to provide a placeholder block, which will be displayed before the component is lazy loaded.&lt;/p&gt;

&lt;p&gt;I've created a simple video placeholder to do the needful - which also caters for showing a loader when the input is passed (more about loading block is below)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app-placeholder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MatIconModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MatProgressSpinnerModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;
      @if(loading) {
      &amp;lt;mat-progress-spinner [diameter]="50" mode="indeterminate" /&amp;gt;
      } @else {
      &amp;lt;mat-icon&amp;gt;play_circle&amp;lt;/mat-icon&amp;gt;
      }
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlaceholderComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this is how the defer block looks now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer(on viewport) {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @placeholder {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when we reload the app, we'll notice our new lazy loaded chunk is not loaded instantly. But it only does so when we scroll down to the &lt;code&gt;VideoComponent&lt;/code&gt;. This is the viewport trigger in action!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nice :)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--APpv5-rW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/without-lazy-load.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--APpv5-rW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/without-lazy-load.png" alt="Video with viewport" width="800" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Timer trigger
&lt;/h3&gt;

&lt;p&gt;The timer trigger will cause lazy loading to occur only after a specified number of milliseconds or seconds pass.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer(on timer(5s)) {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @placeholder {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test it out, we can give a 5s duration and then see the lazy loading in action. It's useful for when you want to load different parts of the UI with slight intervals - to give a &lt;strong&gt;nice, smooth&lt;/strong&gt; loading experience!&lt;/p&gt;

&lt;h3&gt;
  
  
  Hover trigger
&lt;/h3&gt;

&lt;p&gt;The hover trigger will cause lazy loading to occur when the user hovers over the placeholder element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer(on hover) {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @placeholder {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Hover trigger is a superb indication of user interest so it makes sense to use when you want to prepare the UI for the user doing something.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interaction trigger
&lt;/h3&gt;

&lt;p&gt;The interaction trigger will cause lazy loading to occur only after the user actually interacts (i.e. clicks) on the placeholder element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer(on interaction) {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @placeholder {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Combination of triggers
&lt;/h3&gt;

&lt;p&gt;A user can also set the Timer, Viewport and other triggers to work in conjunction such that lazy loading will occur once either of these two events occur.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer(on viewport; on timer(5s)) {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @placeholder {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prefetching chunks
&lt;/h3&gt;

&lt;p&gt;One interaction pattern that can be really useful here is in combination of hover and interaction triggers - by also utilizing the &lt;code&gt;prefetch&lt;/code&gt; option.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefetching is the loading of a resource before it is required to decrease the time waiting for that resource. &lt;a href="https://www.techopedia.com/definition/32421/prefetching"&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the defer block, &lt;code&gt;prefetch&lt;/code&gt; can be used with any of the triggers discussed before. So for example, we can &lt;strong&gt;prefetch&lt;/strong&gt; the chunks we need for the player on &lt;strong&gt;hover&lt;/strong&gt;, while only render them with the &lt;strong&gt;interaction&lt;/strong&gt; trigger.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This will decrease the wait time further - because hovering usually indicates user interest in the UI element!&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer(prefetch on hover; on interaction) {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @placeholder {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So you can see how the &lt;code&gt;defer&lt;/code&gt; block provides such a lot of flexibility to add all kinds of lazy loading behavior to your Angular apps in simple, intuitive code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Loading Subblock
&lt;/h2&gt;

&lt;p&gt;Often, during lazy loading, a UI flicker occurs at the time the lazy loaded component is loading. The solution to this is the &lt;code&gt;@loading&lt;/code&gt; subblock that provides an indicator that the current block is loading.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer(on interaction) {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @placeholder {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @loading {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="na"&gt;[loading]=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But sometimes, the loading is so quick that the loader does not even show up. For this purpose, Angular allows us to specify a minimum amount of time to show this loading subblock before transferring to the component being lazy loaded.&lt;/p&gt;

&lt;p&gt;We give here a 500ms minimum time to show the loader below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@defer(on interaction) {
&lt;span class="nt"&gt;&amp;lt;app-video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @placeholder {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @loading(minimum 500ms) {
&lt;span class="nt"&gt;&amp;lt;app-placeholder&lt;/span&gt; &lt;span class="na"&gt;[loading]=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the User Experience much better!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The final result is an efficient lazy-loaded player that only loads when the user interacts with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b5vCkSmG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/defer-load-youtube-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b5vCkSmG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://zoaibkhan.com/assets/blog/angular-17-defer-block-create-a-lazy-loaded-youtube-player-for-blog/defer-load-youtube-1.gif" alt="Final lazy loaded video player" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Utilizing the power of Defer block in Angular v17 greatly optimizes your Angular app and is easy to use. It offers an array of trigger options that make customizing your user experiences exciting.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The Defer block in Angular v17 brings in a lot of new possibilities to optimize your Angular app and is also pretty intuitive to use."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are even more in-depth features like the when trigger for custom conditions, but those will be covered later.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and see you in the next post!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>lazyloading</category>
      <category>youtube</category>
    </item>
  </channel>
</rss>
