<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Umair Hafeez]]></title><description><![CDATA[Front End Architect | Tech Lead | Full Stack Web Developer | Angular Fanatic 🅰️ | MCP]]></description><link>https://blog.umairhafeez.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1615487644197/eZnlWzqTr.png</url><title>Umair Hafeez</title><link>https://blog.umairhafeez.com</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 17:34:42 GMT</lastBuildDate><atom:link href="https://blog.umairhafeez.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Quick Tip: Centralized Error Handling]]></title><description><![CDATA[Graceful error handling is a key feature of good software.

Angular comes with a built-in mechanism for centralized error handling. It's really handy to deal with unhandled exceptions.
Here is how we can quickly get started.
We'll create a class that...]]></description><link>https://blog.umairhafeez.com/centralized-error-handling-in-angular</link><guid isPermaLink="true">https://blog.umairhafeez.com/centralized-error-handling-in-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[error handling]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Tue, 09 Nov 2021 04:52:11 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>Graceful error handling is a key feature of good software.</p>
</blockquote>
<p>Angular comes with a built-in mechanism for centralized error handling. It's really handy to deal with unhandled exceptions.</p>
<p>Here is how we can quickly get started.</p>
<p>We'll create a class that extends ErrorHandler that is part of <code>@angular/core</code> and implement the handleError method, that gives us the <code>error</code> object.</p>
<pre><code><span class="hljs-keyword">import</span> { NgModule, ErrorHandler } from <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomErrorHandler</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ErrorHandler</span> </span>{
  handleError(error: any) {
    console.warn(<span class="hljs-string">'Handled using custom handler: '</span>, {
      name: error.name,
      message: error.message,
      stack: error.stack || <span class="hljs-string">''</span>
    });
  }
}

<span class="hljs-meta">@NgModule</span>({
  providers: [
    {
      provide: ErrorHandler,
      useClass: CustomErrorHandler
    }
  ]
})
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppModule</span> </span>{ }
</code></pre><p>We can use any logging provider to log these errors and present the user with a friendly message to keep up with a good UX.</p>
<p>A working example can be found on this link:</p>
<p>https://stackblitz.com/edit/angular-ivy-resq5p?file=src/app/app.module.ts</p>
<p>I hope you like this tip!</p>
]]></content:encoded></item><item><title><![CDATA[Usage of `alt` attribute and text descriptions when using img elements]]></title><description><![CDATA[A few days ago, I was reading some accessibility guidelines regarding the usage of images in web applications, and I learned a few interesting things which I wanted to share with all of you.
But before we jump to the topic, I must say that the more I...]]></description><link>https://blog.umairhafeez.com/usage-of-alt-attribute-when-using-img-elements</link><guid isPermaLink="true">https://blog.umairhafeez.com/usage-of-alt-attribute-when-using-img-elements</guid><category><![CDATA[Accessibility]]></category><category><![CDATA[Web Accessibility]]></category><category><![CDATA[images]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Fri, 02 Apr 2021 00:57:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1617319566082/DoqRGQYam.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few days ago, I was reading some accessibility guidelines regarding the usage of <strong>images</strong> in web applications, and I learned a few interesting things which I wanted to share with all of you.</p>
<p>But before we jump to the topic, I must say that the more I read about accessibility, the more I am convinced that <code>accessibility is not an option, it is imperative</code>.</p>
<h2 id="foreword">Foreword</h2>
<p>As the famous saying goes:</p>
<blockquote>
<p>A picture is worth a thousand words</p>
</blockquote>
<p><em>But there are people who will need those thousand words because they can't see the picture partially or completely.</em></p>
<h2 id="problem">Problem</h2>
<p>We all know that images are a core part of every web application, but oftentimes, images are not made accessible which may affect a lot of users of your application.</p>
<blockquote>
<p>For most cases, making images accessible is pretty simple</p>
</blockquote>
<p>While using images in our web applications, generally we don't realize that images fall into certain categories/types based on the use cases, and we should handle each use case differently.</p>
<h2 id="types-of-images">Types of Images</h2>
<p>The following are the most commonly known types of images used in web applications.</p>
<ol>
<li><a class="post-section-overview" href="#1-informative">Informative</a> </li>
<li><a class="post-section-overview" href="#2-decorative">Decorative</a> </li>
<li><a class="post-section-overview" href="#3-functional">Functional</a> </li>
<li><a class="post-section-overview" href="#4-group">Group</a> </li>
<li><a class="post-section-overview" href="#5-text-as-image">Text-as-image</a> </li>
<li><a class="post-section-overview" href="#6-image-map">Image Map</a> </li>
<li><a class="post-section-overview" href="#7-complex">Complex</a> </li>
</ol>
<p>Let's take a look at each of these types briefly and how to make images accessible in each use case.</p>
<h3 id="1-informative">1. Informative</h3>
<p>These are the images that represent a concept or a piece of product information, e.g., pictures of people or places, or illustrations.</p>
<p>For such images, the <code>alt</code> text must be descriptive enough to explain the image completely.</p>
<p>Please take time for this and write a proper description for users that use screen readers or assistive technologies, to understand the context.</p>
<h3 id="2-decorative">2. Decorative</h3>
<p>These are the images that are only used to add visual decoration. They don't convey any information and they are not required to understand the page, e.g., icons, styling elements, images with adjacent descriptions.</p>
<p>Use <code>alt=""</code> for such images.</p>
<p>🚫 DO NOT omit <code>alt</code> attribute in any case.</p>
<h3 id="3-functional">3. Functional</h3>
<p>Sometimes we use images as links or buttons. These are called functional images.</p>
<p>The <code>alt</code> text for these images should properly explain the functionality, e.g., "Click to submit the form" or "Click to open abc[dot]com in new window".</p>
<h3 id="4-group">4. Group</h3>
<p>There are situations where a group of images is used to represent one piece of information, e.g., a star rating where a few star icons are used to represent a rating.</p>
<p>In such cases, set the <code>alt</code> text of the first image to describe the entire collection and set <code>alt=""</code> for the rest of the items.</p>
<h3 id="5-text-as-image">5. Text-as-image</h3>
<p>Ideally, we should NOT use readable text in images. This is similar to the <code>Informative</code> use case, but more text content in the image.</p>
<p>But some use cases are pretty common where we present text as images, e.g., logos and article banners.</p>
<p>For logos, the <code>alt</code> text should be the name of the organization or product that the logo represents.</p>
<p>For use cases like banners, the <code>alt</code> text of the image should contain the exact text as that of the image.</p>
<h3 id="6-image-map">6. Image Map</h3>
<p>If you decide to use an image map, which means a single image divided by using multiple clickable <code>area</code> elements, you should make sure that the main image has a descriptive <code>alt</code> text that explains the overall context, and then each <code>area</code> should have its own descriptive alt text.</p>
<h3 id="7-complex">7. Complex</h3>
<p>These are the most tricky type of images. Graphs, charts, diagrams, bigger illustrations, maps are all examples of complex images.</p>
<p>You will need 2 pieces of description for such images, one summarized and the other detailed.</p>
<p>Let's see the options we have.</p>
<p><strong>7.1</strong>: Add <code>alt</code> text with summary and use the <code>aria-describedby</code> attribute to point to an element with detailed information.</p>
<p><strong>7.2</strong>: Add <code>alt</code> text with summary and use the <code>longdesc</code> attribute to point to a URI or section of a page with detailed information.</p>
<p><strong>7.3</strong>: Use <code>figure</code> element with <code>role="group"</code> to wrap the image and use a nested <code>figcaption</code> element to list down all the details.</p>
<p><strong>7.4</strong>: Add <code>alt</code> text with summary and add a link to complete description or actual description beside the image, based on the situation.</p>
<h2 id="summary">Summary</h2>
<p>Last but not least, DO NOT use words like <strong>"image"</strong>, <strong>"photo"</strong> or <strong>"picture"</strong> in the alt text, e.g., <code>image of a dog</code>. The screen readers will infer the <code>&lt;img&gt;</code> and read something like <strong>"image image of a dog"</strong>. This is definitely NOT what your user will like.</p>
<p>As seen in all of the above use cases, there is absolutely no way that we can omit the  <code>alt</code> text. In fact, we must use it with proper and meaningful descriptions.</p>
<hr />
<p>I hope you enjoyed this quick tip and learned something. I would love to hear your valuable feedback.</p>
<p>Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Better yet accessible :focus]]></title><description><![CDATA[Every element of your app that is interactive or needs to be highlighted, should have tabbing focus indicator.
By default, all browsers render an outline as a focus indicator BUT that is different per browser.
As an example, this is how Chrome, Firef...]]></description><link>https://blog.umairhafeez.com/better-yet-accessible-focus</link><guid isPermaLink="true">https://blog.umairhafeez.com/better-yet-accessible-focus</guid><category><![CDATA[CSS]]></category><category><![CDATA[Accessibility]]></category><category><![CDATA[Web Accessibility]]></category><category><![CDATA[tips]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Wed, 31 Mar 2021 07:15:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1617154363008/jlOdLZ-vY.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every element of your app that is interactive or needs to be highlighted, should have tabbing focus indicator.</p>
<p>By default, all browsers render an <code>outline</code> as a focus indicator BUT that is different per browser.</p>
<p>As an example, this is how Chrome, Firefox, and Safari will set focus on the same element.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617174416408/kiCGx6klu.png" alt="focus styling by different browsers.png" /></p>
<p>Although every browser renders an <code>outline</code>, the color of that <code>outline</code> might not work well with your app theme or may not be prominently visible to your users.</p>
<blockquote>
<p>🛑 This is not a good UX and it should be fixed!</p>
</blockquote>
<p>The good news is that we can improve it with CSS. Let's see how.</p>
<p>The following rule will apply a <code>solid blue outline of 2px</code> to all focused elements on your page.</p>
<pre><code>*<span class="hljs-selector-pseudo">:focus</span> {
    <span class="hljs-attribute">outline</span>: <span class="hljs-number">#007EFF</span> solid <span class="hljs-number">2px</span>;
}
</code></pre><p>You can change the color based on your app theme or even for a section of the app by using more specific selectors.</p>
<blockquote>
<p>But wait, there is more!</p>
</blockquote>
<p>The <code>outline</code> will always have corners regardless of the shape of the element. You might want to make it look better and follow the shape of the element.</p>
<p>The following snippet comes to the rescue:</p>
<pre><code>*<span class="hljs-selector-pseudo">:focus</span> {
    <span class="hljs-attribute">outline</span>: transparent solid <span class="hljs-number">2px</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">#fff</span>, <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">4px</span> <span class="hljs-number">#007EFF</span>;
}
</code></pre><p>This is the same button after a pinch of precise CSS (as <a class="user-mention" href="https://hashnode.com/@DashSat">Darshan Satya</a> says).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617174814833/DqouVq45h.png" alt="focus styling by different browsers (1).png" /></p>
<p>You must be wondering why do we have a transparent <code>outline</code> and a colored <code>box-shadow</code>.</p>
<p>Well, the fact of the matter is that <code>box-shadow</code> is not visible in Windows High Contrast mode, and we need the <code>outline</code> so the <code>transparent</code> color can be overridden and used by the OS.</p>
<p>I hope you liked this tip and I will love to hear your feedback.</p>
<p>Happy coding! </p>
]]></content:encoded></item><item><title><![CDATA[Being a better Interviewer]]></title><description><![CDATA[We talk a lot about how one should prepare and then appear in interviews. But no one talks about what is expected from the interviewer to improve the overall interview experience.
Let's turn the tables today!
What should the interviewer do to make th...]]></description><link>https://blog.umairhafeez.com/being-a-better-interviewer</link><guid isPermaLink="true">https://blog.umairhafeez.com/being-a-better-interviewer</guid><category><![CDATA[interview]]></category><category><![CDATA[Self Improvement ]]></category><category><![CDATA[best practices]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Sat, 23 Jan 2021 08:56:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1611384096478/uL4F4f9lI.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We talk a lot about how one should prepare and then appear in interviews. But no one talks about what is expected from the interviewer to improve the overall interview experience.</p>
<p><strong><em>Let's turn the tables today!</em></strong></p>
<h3 id="what-should-the-interviewer-do-to-make-the-interview-better">What should the interviewer do to make the interview better?</h3>
<p>Here's what I learned and try to practice when I'm interviewing someone.</p>
<h4 id="be-on-time">Be on time</h4>
<blockquote>
<p>Time matters to them as much as it matters to us! </p>
</blockquote>
<p>When the interview is scheduled, add a reminder on your calendar for at least 2 hours before the interview. This way, you will have enough time to wrap up if you are working on anything important.</p>
<p>If the interview is online, try to find a peaceful corner before the schedule time and join the meeting on time.</p>
<p>But if the interview is in-person, make sure that you have a room booked before the interview time and follow your company's protocol to escort the interviewee to the interview room.</p>
<h4 id="introduction">Introduction</h4>
<p>Make them feel welcomed, and follow these initial steps:</p>
<ul>
<li>Always start with a little introduction of yourself</li>
<li>Request them to introduce themselves and share their experiences &amp; areas of strength</li>
<li>If they share something interesting or any of their achievements, compliment it properly</li>
</ul>
<p>This will give them time to settle and get in a good rhythm.</p>
<h4 id="main-course">Main Course</h4>
<p>Better stick to the role requirements and/or what's in their resume. Don't under-ask or over-ask based on what you're looking for.</p>
<p>In my personal experience, I have been into situations where the interviewer got derailed towards discussions which were either not relevant to the job role or not in my past experience. These situations demotivated me big time during the interview. </p>
<h4 id="when-to-dive-deep">When to dive deep?</h4>
<p>Only dive deep into the core role requirements or when they speak really high about something.</p>
<p>For instance, if you are looking for an Angular developer, most of your interview time should be spent on topics related to Angular, and then HTML, CSS and other related stuff.</p>
<p>Or, if they express that they are really expert in something, and you have also good knowledge of that topic, you can dig deeper to see if they really know their strengths or not. </p>
<h4 id="timebox">Timebox</h4>
<p>Don't forget that you have limited time and you have to cover it all, and leave time for them to ask any questions they may have.</p>
<p>I generally keep interviews to one hour, and divide it like this:</p>
<ul>
<li>Introduction - 5 minutes</li>
<li>Core Topic - 25 minutes</li>
<li>Related Topics - 25 minutes</li>
<li>Q&amp;A - 5 minutes</li>
</ul>
<h4 id="stay-organized">Stay organized</h4>
<p>Don't jump between topics while asking questions. Stay organized and assess role requirements one by one.</p>
<p>Take your short notes, if you think you can forget something.</p>
<h4 id="be-empathetic">Be empathetic</h4>
<p>This is very, very important!</p>
<p>If they lack core knowledge required for the job, try conveying it in a constructive way. May be something like:</p>
<p>"You're good in other areas, but I'm afraid you'll need more time to learn this. Don't worry, it's not too difficult to learn."</p>
<p>If they lack knowledge of minor concepts, correct them right away. This way, you're actually helping them out to know and fix their weak areas.</p>
<p>Try to mentor them with tips and advices, so they can prepare better for their next attempt.</p>
<p>Don't ever disrespect or belittle anyone if they don't perform per your expectations. They might be in a situation we don't know.</p>
<p>And never ever let them feel in case you are not satisfied. Don't change your tone or the flow of the interview. Great advice by my friend <a target="_blank" href="https://hashnode.com/@OliverJumpertz">Oliver Jumpertz</a>. </p>
<h4 id="what-if-its-a-disaster-from-start">What if it's a disaster from start?</h4>
<p>Sometimes you might end up with someone who clearly does not fit the role. Still give them some time before you decide to end the interview earlier than expected.</p>
<p>I try asking a few questions from their resume, so they don't get a bad feeling.</p>
<p>Remember, empathy is important! </p>
<h4 id="ending">Ending</h4>
<p>No matter how it went, give them some time to ask any questions they may have.</p>
<p>Try to answer all questions <strong>except</strong> the ones related to salary or outcome of the interview.</p>
<p>I always say something like this: "I will share my feedback with the recruitment team, and they'll take it up from there."</p>
<p>Close positively by wishing them luck.</p>
<p>Remember, you're representing your organization and YOU are the one who's looking for a good resource. You must present it in a way that it creates a good image of yourself and your organization.</p>
<p>These are all my opinions. I'll love to hear yours and may be correct myself too 😊</p>
<blockquote>
<p>Banner image by <a target="_blank" href="https://www.pexels.com/@tima-miroshnichenko?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels">Tima Miroshnichenko</a> from <a target="_blank" href="https://www.pexels.com/photo/man-in-black-long-sleeve-shirt-sitting-beside-man-in-blue-dress-shirt-5439376/?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels">Pexels</a></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Web Animations and Accessibility]]></title><description><![CDATA[In the modern web era, animations are one of the core features of user interfaces. Only a few years ago, animations were only possible with JavaScript, and there was minimal support for animations in CSS. However, with the dawn of CSS 3, web animatio...]]></description><link>https://blog.umairhafeez.com/web-animations-and-accessibility</link><guid isPermaLink="true">https://blog.umairhafeez.com/web-animations-and-accessibility</guid><category><![CDATA[animations]]></category><category><![CDATA[Accessibility]]></category><category><![CDATA[CSS Animation]]></category><category><![CDATA[Web Accessibility]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Tue, 19 Jan 2021 05:10:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1611032565514/uF3sSCiK3X.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the modern web era, animations are one of the core features of user interfaces. Only a few years ago, animations were only possible with JavaScript, and there was minimal support for animations in CSS. However, with the dawn of CSS 3, web animations have taken a huge leap and there are so many brilliant developers who can create astonishing user interfaces using CSS animations only.</p>
<p>There are so many common use cases of animations, including bulging buttons, carousels, parallax, and accordions. But there is a very important aspect to be considered while using animations, i.e. <code>Accessibility</code>.</p>
<p>Although animations look very cool, but that might not be the case with all of the users of your application. There are people who suffer from seasickness aka motion sickness, and some with vestibular motion disorder. These people will have a lot of problem using the interfaces with animations, and in some cases, the animations might affect them adversely.</p>
<h3 id="how-to-cope-with-this-situation">How to cope with this situation?</h3>
<p>By taking this fact into consideration, pretty much all operating systems provide options to reduce motion, so the users see less movements while using their devices. This also applies to website or web applications they use in their favorite web browsers. </p>
<p>And the good news is that all web browsers are enabled to access the user's accessibility settings and make it available to the developers, so they can write their CSS and JavaScript accordingly.</p>
<h3 id="css-animations">CSS Animations</h3>
<p>If you are using CSS animations, you can use the <code>prefers-reduced-motion</code> media query to read user's settings and disable/reduce your animations accordingly.</p>
<p>Here is how your CSS should look like.</p>
<pre><code>// Supported <span class="hljs-keyword">by</span> <span class="hljs-keyword">all</span> browsers <span class="hljs-keyword">except</span> IE
@media (prefers-reduced-motion: reduce) {
    // your styles <span class="hljs-keyword">with</span> reduced <span class="hljs-keyword">or</span> <span class="hljs-keyword">no</span> animations
}
</code></pre><p>Or it can be only <code>@media (prefers-reduced-motion)</code> to keep things simpler.</p>
<h3 id="javascript-animations">JavaScript Animations</h3>
<p>In case you have animations implemented using JavaScript, you can use the <code>window.matchMedia</code> method to check for the value of <code>prefers-reduced-motion</code> setting.</p>
<p>Here is how your script should look like.</p>
<pre><code><span class="hljs-keyword">window</span>.matchMedia(<span class="hljs-string">'(prefers-reduced-motion)'</span>);
</code></pre><p>It will return an object of type <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList">MediaQueryList</a> which looks like this:</p>
<pre><code>{
  <span class="hljs-attr">media:</span> <span class="hljs-string">"(prefers-reduced-motion)"</span>,
  <span class="hljs-attr">matches:</span> <span class="hljs-literal">false</span>,
  <span class="hljs-attr">onchange:</span> <span class="hljs-literal">null</span>
}
</code></pre><p>The most important value here is the boolean property <code>matches</code>. If it has a value of <code>true</code>, you can disable/reduce animations safely. You can store this object in a class level or global storage so your application can access it.</p>
<blockquote>
<p>That is pretty much all you need to help users with seasickness or vestibular motion disorder to visit your website or web application without any problem.</p>
</blockquote>
<p>But wait, there is one more thing that we can do to enhance it a little bit. What if the user toggles the reduce motion settings on the fly?</p>
<p>The CSS media query will respond immediately, but the JavaScript solution will require a page load because we're reading the value only once and storing it for reuse. This doesn't sound like a good user experience.</p>
<p>You might have noticed that there is a 3rd property in the <code>MediaQueryList</code> response, that is, <code>onchange</code>. This is an event, which is emitted by the browsers when the value of target media query is changed. We can simply add an event handler and listen to this even, and then update our application accordingly.</p>
<p>This is a very simple example of how your can do it.</p>
<pre><code><span class="hljs-keyword">const</span> motionMediaMatch = <span class="hljs-built_in">window</span>.matchMedia(<span class="hljs-string">'(prefers-reduced-motion)'</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">motionMediaMatchListener</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (motionMediaMatch.matches) {
    <span class="hljs-comment">// disable or reduce animations</span>
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// enable or resume animations</span>
  }
}

motionMediaMatch.addEventListener(<span class="hljs-string">'change'</span>, motionMediaMatchListener);
</code></pre><p>And we are done 🙌🏻</p>
<h3 id="take-away">Take Away</h3>
<p>Accessibility is not an option, it is an imperative! We, developers, should seriously take accessibility in to consideration and make sure that whatever we build, it should be as accessible as possible.</p>
<p>Happy learning, happy coding!</p>
<blockquote>
<p><span>Banner image by <a href="https://unsplash.com/@pankajpatel?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Pankaj Patel</a> on <a href="https://unsplash.com/s/photos/animation-accessibility?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Developing & Deploying a Google Chrome Extension]]></title><description><![CDATA[Google Chrome is one of the most used web browsers for so many reasons, and extensions are one of those. Ever since I started using Google Chrome, I have been using so many useful extensions built by some amazing people.
I always wanted to explore ho...]]></description><link>https://blog.umairhafeez.com/developing-and-deploying-a-google-chrome-extension</link><guid isPermaLink="true">https://blog.umairhafeez.com/developing-and-deploying-a-google-chrome-extension</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[Google Chrome]]></category><category><![CDATA[build]]></category><category><![CDATA[deployment]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Sat, 09 Jan 2021 07:55:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1610178914037/89-Pab8Yo.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Google Chrome is one of the most used web browsers for so many reasons, and extensions are one of those. Ever since I started using Google Chrome, I have been using so many useful extensions built by some amazing people.</p>
<p>I always wanted to explore how these extensions are built and distributed. So recently, I decided to give it a shot and learn the basics. I wanted to practice what I learn, so I thought of a simple idea and started building a tiny extension.</p>
<p>I thought of a personal reminder extension that displays a notification based on the selected configuration. I've named it <code>Aqua Buddy</code> because it reminds me of drinking water. Let's go step by step and build it together 🙌🏼</p>
<h2 id="getting-started">Getting Started</h2>
<blockquote>
<p>At the core, Google Chrome Extensions are nothing but a combination of HTML, CSS, and JavaScript code organized in a specific pattern.</p>
</blockquote>
<p>An extension starts with a <a target="_blank" href="https://www.json.org/">JSON</a>-formatted manifest file called <em><a target="_blank" href="https://developer.chrome.com/extensions/manifest">manifest.json</a></em> file, that contains all the meta data about your extension, for example, name, description, and version of the extension that is displayed on the Chrome Web Store and when the extension is installed.</p>
<blockquote>
<p>The <code>manifest.json</code> file should be placed at the root of the extension directory that contains the final distributable code.</p>
</blockquote>
<p>Let's create an empty directory for your extension and create the <code>manifest.json</code> file with the following content.</p>
<pre><code>{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Aqua Buddy"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"I'm your friend 💙 and I'm here to help you stay hydrated!"</span>,
  <span class="hljs-attr">"manifest_version"</span>: <span class="hljs-number">2</span>
}
</code></pre><blockquote>
<p>Please note that <code>manifest_version</code> must have a value 2, because version 1 has been deprecated since Chrome 18.</p>
</blockquote>
<p>With only the manifest file in place, you can load it in the Chrome browser. Of course it won't have any interface or any functionality, but it will be listed in the extensions area. Please follow these steps to load your empty extension.</p>
<ol>
<li>Navigate to <code>chrome://extensions</code> OR open the <code>Extensions</code> page using the <code>Settings -&gt; More Tools -&gt; Extensions</code> menu.</li>
<li>Once you're there, enable the <code>Developer mode</code> using the toggle button the <code>top right</code> corner.</li>
<li>Once you enable the <code>Developer mode</code>, you'll see a few buttons on the top. Click the button called <code>Load unpacked</code>.</li>
<li>It will open a directory selection dialog</li>
<li>Navigate to your extension directory that contains the manifest file and select that directory.</li>
<li>You will see your extension being listed with the name, description and version you provided, like below.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1601788567750/pO95GByRU.png" alt="Screen Shot 2020-10-04 at 1.15.42 AM.png" /></li>
</ol>
<p>Congratulations!!! You have completed your first step, let's make it look beautiful.</p>
<h2 id="adding-icons">Adding Icons</h2>
<p>To distinguish and identify your extension visually, you will need icons. If you have an icon set, it's great, otherwise you can find icons from the tons of freely available resources. One of many resources is <em><a target="_blank" href="https://www.flaticon.com/">flaticon</a></em>, which has a huge collection of beautiful icons. For your extension, you will need following dimensions:</p>
<ul>
<li>16x16 =&gt; This will be used as <code>favicon</code> for your extension</li>
<li>32x32 =&gt; This is often needed for Windows computers</li>
<li>48x48 =&gt; This will be used on the extensions management page</li>
<li>128x128 =&gt; This will be displayed on installation and in the Chrome Web Store</li>
</ul>
<blockquote>
<p>If you're using a free icon set, please make sure to give credit to the creator as a goodwill gesture. Please note that some websites make it mandatory in order to allow you to use free resources.</p>
</blockquote>
<p>After downloading the icons, place them inside a sub-directory that lives next to your manifest file, and update your manifest file like below.</p>
<pre><code>{
  <span class="hljs-keyword">...</span>
  <span class="hljs-string">"icons"</span>: {
    <span class="hljs-string">"16"</span>: <span class="hljs-string">"images/aqua-buddy-16.png"</span>,
    <span class="hljs-string">"32"</span>: <span class="hljs-string">"images/aqua-buddy-32.png"</span>,
    <span class="hljs-string">"48"</span>: <span class="hljs-string">"images/aqua-buddy-48.png"</span>,
    <span class="hljs-string">"128"</span>: <span class="hljs-string">"images/aqua-buddy-128.png"</span>
  }
}
</code></pre><p>Go to the extensions management page, locate the card for your extension and click the <code>Reload</code> button, and you will see the icon being displayed. These icons are used for the extension management page, the permissions warning, and favicon.</p>
<p>At this point, you will see that the extension icon is greyed out because we haven't added any functionality or user interface to the extension.</p>
<blockquote>
<p>Cool, let's get to real work now by adding some visual elements.</p>
</blockquote>
<h2 id="user-interface">User Interface</h2>
<blockquote>
<p>The extension user interface should be purposeful and minimal.</p>
</blockquote>
<p>Chrome extensions support multiple types of interfaces and UI features listed below, some of which are required and some are optional.</p>
<h3 id="browser-action">Browser Action</h3>
<p>This is the most commonly used configuration, when your extension is supposed to be working in most cases. Let's register the <code>browser_action</code> field in the manifest file.</p>
<pre><code>{
  <span class="hljs-keyword">...</span>
  <span class="hljs-string">"browser_action"</span>: {
  }
}
</code></pre><p>By adding this, the extension icon will be colorized, which means the extension is available for use, but it doesn't do anything yet.</p>
<h3 id="page-action">Page Action</h3>
<p>Use this configuration if your extension should be available on certain pages based on some logic. The extension icon will be colorized only when it is available for use, otherwise it will be greyed out.</p>
<p>To define the rules that enable or disable the extension, you will have to use the <a target="_blank" href="https://developer.chrome.com/declarativeContent">declarativeContent</a> API.</p>
<blockquote>
<p>We don't need any page specific logic in our extension, so we will use "browser_action" configuration.</p>
</blockquote>
<h3 id="icons">Icons</h3>
<p>If you want to display a different icon in the toolbar, you can register it in the manifest file using the <code>default_icon</code> field in the <code>browser_action</code> or <code>page_action</code> section based on your set up. If this icon is not provided, Chrome will use the icon you provided in the <code>icons</code> section in the manifest file. If that is also not present, Chrome will use a default icon.</p>
<blockquote>
<p>Recommendation is to use square png images and provide at least 16x16 and 32x32 sizes.</p>
</blockquote>
<p>For this example, we will use the same icon that we have used in the <code>icons</code> section, so our updated manifest file looks like this:</p>
<pre><code>{
  <span class="hljs-keyword">...</span>
  <span class="hljs-string">"browser_action"</span>: {
    <span class="hljs-string">"default_icon"</span>: {
      <span class="hljs-string">"16"</span>: <span class="hljs-string">"images/aqua-buddy-16.png"</span>,
      <span class="hljs-string">"24"</span>: <span class="hljs-string">"images/aqua-buddy-24.png"</span>,
      <span class="hljs-string">"32"</span>: <span class="hljs-string">"images/aqua-buddy-32.png"</span>,
      <span class="hljs-string">"64"</span>: <span class="hljs-string">"images/aqua-buddy-64.png"</span>,
      <span class="hljs-string">"128"</span>: <span class="hljs-string">"images/aqua-buddy-128.png"</span>,
      <span class="hljs-string">"256"</span>: <span class="hljs-string">"images/aqua-buddy-256.png"</span>,
      <span class="hljs-string">"512"</span>: <span class="hljs-string">"images/aqua-buddy-512.png"</span>
    }
  }
}
</code></pre><p>Great, now our basic set up is completed. Let's get to implement the main functionality of our extension.</p>
<p>There are a number of UI features available to use, which are listed at the end of this article, but we will be using a <a target="_blank" href="https://developer.chrome.com/extensions/browserAction#popups">Popup</a> that will be shown when the users will click the browser icon.</p>
<h3 id="popup-template">Popup Template</h3>
<p>We will create a file called <code>popup.html</code> in the root folder, with <a target="_blank" href="https://raw.githubusercontent.com/umairhm/aqua-buddy/master/popup.html">these</a> contents.</p>
<blockquote>
<p>I have included a trimmed down version of <a target="_blank" href="https://tailwindcss.com/">Tailwind CSS</a> and some custom CSS in the <a target="_blank" href="https://raw.githubusercontent.com/umairhm/aqua-buddy/master/css/aqua-buddy.min.css">./css/aqua-buddy.min.css</a> file.</p>
</blockquote>
<p>This template means nothing until we link it with the extension. So let's get back to our <code>manifest.json</code> file and link it under the <code>browser_action</code> section like this:</p>
<pre><code>{
  <span class="hljs-keyword">...</span>
  <span class="hljs-string">"browser_action"</span>: {
    <span class="hljs-string">"default_title"</span>: <span class="hljs-string">"Aqua Buddy"</span>,
    <span class="hljs-string">"default_popup"</span>: <span class="hljs-string">"popup.html"</span>,
    <span class="hljs-keyword">...</span>
  },
  <span class="hljs-keyword">...</span>
}
</code></pre><blockquote>
<p>You might have noticed <code>default_title</code> being added along with <code>default_popup</code> entry. It will simply show a <a target="_blank" href="https://developer.chrome.com/extensions/user_interface#tooltip">Tooltip</a> when you hover over the extension icon.</p>
</blockquote>
<p>Once that is done, if we refresh the extension and click the extension icon, this is how it will look like.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1610168942379/RkHZrEFv1.png" alt="Screen Shot 2021-01-09 at 12.08.39 AM.png" /></p>
<p>Hoooray!!!</p>
<p>Now that we have the template ready, we need some <code>JavaScript</code> magic to make it work and show us those helpful notifications.</p>
<h3 id="extension-script">Extension Script</h3>
<p>The Chrome extension need to know what events it should be listening to, for example, when the extension is installed or a change in storage or events emitted by other APIs. Such scripts have to be kept in separate files and registered under <code>background</code> section of the <code>manifest.json</code> file, like this:</p>
<pre><code>{
  <span class="hljs-keyword">...</span>
  <span class="hljs-string">"background"</span>: {
    <span class="hljs-string">"scripts"</span>: [<span class="hljs-string">"background.js"</span>],
    <span class="hljs-string">"persistent"</span>: false
  },
  <span class="hljs-keyword">...</span>
}
</code></pre><blockquote>
<p>You can register multiple background scripts to modularize your code.
The <strong>persistent</strong> property should be kept "false" according to the official <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv2/background_pages/#manifest">docs</a>.</p>
</blockquote>
<p>Once these scripts are registered, the extension scans it for all registered events in these scripts.</p>
<p>As we are building an extension for notifications based on user's selected configurations, we will need access to:</p>
<ul>
<li><a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/notifications/">notifications</a> API to show the notifications</li>
<li><a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/alarms/">alarms</a> API to trigger notifications based on the user's configuration</li>
<li><a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/storage/">storage</a> API to preserve user's configurations</li>
</ul>
<p>To consume these APIs, we will have to request permissions from the browser. The permissions can be registered in the <code>manifest.json</code> file like this:</p>
<pre><code>{
  <span class="hljs-keyword">...</span>
  <span class="hljs-string">"permissions"</span>: [<span class="hljs-string">"alarms"</span>, <span class="hljs-string">"notifications"</span>, <span class="hljs-string">"storage"</span>],
  <span class="hljs-keyword">...</span>
}
</code></pre><p>Let's create a file named <code>background.js</code> and put <a target="_blank" href="https://raw.githubusercontent.com/umairhm/aqua-buddy/master/background.js">these</a> contents in that file.</p>
<blockquote>
<p>Please note that the API events need to be registered on the global level, without nesting inside any method, otherwise the events don't work as expected.</p>
</blockquote>
<p>You can see that we have 3 event handlers registered at the end of our <code>background.js</code> file, which call further methods declared above. I have tried to keep the method names self explanatory.</p>
<blockquote>
<p>You might have noticed that we are linking a file <code>popup.js</code> in our <code>popup.html</code> file, which is to handle the popup logic.</p>
</blockquote>
<h3 id="popup-script">Popup Script</h3>
<p>As per official documentation, a popup is just another web page but it <strong>does not allow inline scripts</strong>. So how can we handle events from our UI elements like buttons or dropdowns?</p>
<p>We can use DOM API to listen to page events and register events for UI elements as well. For example:</p>
<pre><code><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// This is where we can register and handle the page events and implement other logic</span>
});
</code></pre><p>Let's add <a target="_blank" href="https://raw.githubusercontent.com/umairhm/aqua-buddy/master/popup.js">these</a> contents to our <code>popup.js</code> file.</p>
<blockquote>
<p>Please note that we are registering all the events every time the popup is loaded, because Chrome destroys the popup and the linked files once it is closed.</p>
</blockquote>
<h4 id="refresh-the-extension-and-ta-da-you-have-a-working-chrome-extension"><em>Refresh the extension, and ta-da, you have a working Chrome Extension!!!</em></h4>
<h3 id="packaging-for-deployment">Packaging for Deployment</h3>
<p>To get your extension published on to Chrome Web Store, you will have to put all the contents including images &amp; icons in a <code>zip</code> file. You can use any JavaScript package to minify your HTML, CSS and JavaScript files before creating the <code>zip</code> file.</p>
<h3 id="deploying-the-extension">Deploying the extension</h3>
<p>To make your extension available in the Chrome Web Store, you need to register as a  <a target="_blank" href="https://developer.chrome.com/docs/webstore/register/">Chrome Web Store Developer</a>.</p>
<p>Once you have the account created, you can visit the <a target="_blank" href="https://chrome.google.com/webstore/devconsole">Developer Dashboard</a> and click the <code>New Item</code> button.</p>
<p>You will see a popup, where you will be asked to upload the <code>zip</code> file you just created. After uploading the file, you will be taken to details section where you will be asked to provide a bunch of information about your extension including justifications of the permissions your requested in the <code>manifest.json</code> file, a bunch of declarations based on what type of data your extension will consume, and the regions you want to choose for distribution.</p>
<p>After filling all the required information, you can finally submit the extension for automated review process. As soon as the review is complete, the extension will be published on the Chrome Web Store.</p>
<blockquote>
<p>Sometimes, manual review might be needed based on the permissions and the implementation of the extension, which will increase the review times.</p>
</blockquote>
<p>Your extension will be listed on the Developer Dashboard and the status will be changed once it is published publicly.</p>
<h3 id="maintenance">Maintenance</h3>
<p>Once your extension is published, you might want to check the statistics like number of downloads and ratings by the users. You can do that by clicking on the extension from the Developer Dashboard and clicking on the <code>Stats</code> and <code>Ratings</code> options in the left side menu.</p>
<p>You might also want to add new features and make it more beneficial for the users.</p>
<p>The good news is that you can do it as many times as you want, by following these steps:</p>
<ul>
<li>Update the extension code</li>
<li>Update the <code>version</code> in the <code>manifest.json</code> file</li>
<li>Create the zip file from the final code</li>
<li>Go to extension details page by clicking on the extension in the Developer Dashboard page</li>
<li>Click on <code>Package</code> option in the left side menu</li>
<li>Click on <code>Upload new package</code> button in the top right corner</li>
<li>Upload the new zip file</li>
<li>Optionally update the other information if required</li>
<li>Click <code>Submit for review</code> in the top right corner</li>
</ul>
<p>And that is all!!!</p>
<h3 id="other-ui-features">Other UI Features</h3>
<ol>
<li><p><strong>Popup</strong> (<a target="_blank" href="https://developer.chrome.com/extensions/browserAction#popups">Docs</a>):
This is the UI that is displayed when you click an extension's icon in the toolbar. It is nothing but an HTML page with links to stylesheets and script files. The only difference is that it <strong>does not</strong> allow inline JavaScript.</p>
</li>
<li><p><strong>Tooltip</strong> (<a target="_blank" href="https://developer.chrome.com/extensions/user_interface#tooltip">Docs</a>): A tooltip is displayed to the users when they hover over the browser icon. Tooltips can be registered in the manifest file as <code>default_title</code> under the <code>browser_action</code> or <code>page_action</code> section based on your set up.</p>
</li>
<li><p><strong>Omnibox</strong> (<a target="_blank" href="https://developer.chrome.com/extensions/omnibox">Docs</a>): The Chrome's address bar is called <code>omnibox</code>, which provides an API to let the user interact with your extension directly through the <code>omnibox</code>, based on the registered keyword. The following is an example of YouTube's omnibox implementation.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607308694863/1MQ77QLRd.png" alt="Screen Shot 2020-12-06 at 9.37.14 PM.png" /></p>
</li>
<li><p><strong>Context Menu</strong>: (<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/contextMenus/">Docs</a>): You can use the <code>chrome.contextMenus</code> API to add items to Chrome's context menu. You will have to add <code>contextMenus</code> to the permissions section in the <code>manifest</code> file.</p>
</li>
<li><p><strong>Commands</strong>: (<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/commands/">Docs</a>): You can define commands in bind them to different key combinations. There is a section for <code>commands</code> in the <code>manifest</code> file, where you can define all your commands and the respective key combinations.</p>
</li>
<li><p><strong>Override Pages</strong>: (<a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/override/">Docs</a>): You can create an extension to override and replace History, New Tab or Bookmarks web page with your own custom web page. A very common example these days is the New Tab page by <a target="_blank" href="https://daily.dev/">daily.dev</a>.</p>
</li>
</ol>
<h3 id="conclusion">Conclusion</h3>
<p>You might feel overwhelmed with a lot of information, but I tried to gather as much information here as I can, because the official documentation is pretty scattered at the moment.</p>
<p>I really hope you will like it and add a little value to your learning.</p>
<p>Please feel free to share you feedback in the comments, especially if you feel if I missed something or if something needs improvement.</p>
<p>Also, don't forget to download and install <a target="_blank" href="https://chrome.google.com/webstore/detail/aqua-buddy/kidoeajcechhpbhmbeligfiakhhlchom">this tiny little extension</a> that will help you stay hydrated 🙌🏻</p>
<p>Happy learning!</p>
]]></content:encoded></item><item><title><![CDATA[My journey to a successful IELTS Exam]]></title><description><![CDATA[I've been asked a lot of times about my IELTS (General) preparation and how did I manage to get a very good band in the 1st attempt.
So I thought that I'll share my journey and learning with all of you.

First thing first, please take the fear of fai...]]></description><link>https://blog.umairhafeez.com/my-journey-to-a-successful-ielts-exam</link><guid isPermaLink="true">https://blog.umairhafeez.com/my-journey-to-a-successful-ielts-exam</guid><category><![CDATA[learning]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Mon, 21 Sep 2020 03:00:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1600657208541/b8469YsIB.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've been asked a lot of times about my IELTS (General) preparation and how did I manage to get a very good band in the 1st attempt.</p>
<p>So I thought that I'll share my journey and learning with all of you.</p>
<blockquote>
<p>First thing first, please take the fear of failure and stress, out of your way.</p>
<p>It's just a matter of willful preparation &amp; commitment and nothing else.</p>
</blockquote>
<h2 id="introduction">Introduction</h2>
<p>IELTS has 4 modules:</p>
<ol>
<li>Listening</li>
<li>Reading</li>
<li>Writing</li>
<li>Speaking</li>
</ol>
<p>The first 3 are scheduled together in the same sequence, while speaking can be scheduled on the same day or any other day of your convenience.</p>
<p>I personally preferred the same day after other tests and get at once.</p>
<h2 id="getting-started">Getting Started</h2>
<p>Before starting the preparation, judge yourself for all the 4 parts and figure out your weakest to strongest areas.</p>
<p>Mine was listening, so I started preparing for listening. Also, listening is the first module to be tested on the exam day.</p>
<p>When I started my presentation, I found the best resource, in my opinion:</p>
<p><a target="_blank" href="http://ieltsliz.com">IELTS Liz</a> </p>
<p>Ms. Liz (Elizabeth) is a professional IELTS trainer and she has shared a ton of learning material on her website for all 4 modules.</p>
<blockquote>
<p>Bookmark this website and you'll do yourself a favor.</p>
</blockquote>
<h2 id="listening">Listening</h2>
<p>It is more about focusing on and paying keen attention to the details.</p>
<p>I did extensive research online for free resources to help myself prepare for the listening exam and found 2 really valuable resources, that are totally free.</p>
<ol>
<li><a target="_blank" href="https://www.esl-lab.com/">Randall’s ESL Cyber Listening Lab</a>: It has a very good amount of sample listening tests with easy, medium, and hard levels along with a lot of other information. <em>This was my main winning tool in the listening exam.</em></li>
<li>BBC Learning English app  ( <a target="_blank" href="https://play.google.com/store/apps/details?id=uk.co.bbc.learningenglish&amp;hl=en_CA">Android</a> ) ( <a target="_blank" href="https://apps.apple.com/us/app/bbc-learning-english/id1416610731">iOS</a> ): This is a free app available on Google Play and Apple App Store. It has small audio clips that help build vocabulary and improve listening. <em>This is super convenient because it is all audio, so you can listen to it any time you want to.</em></li>
</ol>
<h2 id="reading">Reading</h2>
<p>This module is generally easy if you have good reading speed, practice reading whatever you like.</p>
<p>I found an amazing trick somewhere for the question where you have to match headings with paragraphs, and the trick really worked for me.</p>
<ol>
<li>Read the first paragraph completely and carefully. It is the introduction of everything in the subsequent paragraphs.</li>
<li>Read ONLY the first sentence of all subsequent paragraphs. It is the introduction of that particular paragraph and has all information you need.</li>
<li>Read the last sentence of the last paragraph. It is the summary of the whole text above.</li>
<li>Jump to the questions as soon as possible.</li>
</ol>
<p>For the question where you have to fill the blanks or missing words, DO NOT write a word from your own, copy words from the text.</p>
<h2 id="writing">Writing</h2>
<p>This is generally the hardest module of all, and the only way to succeed is to practice writing as much as possible.</p>
<p>The most important thing is to practice complex sentences, with proper punctuation. It will win you good points!</p>
<h2 id="speaking">Speaking</h2>
<p>This is easy but interesting. The big misconception is that you have to have a good accent. Which is totally wrong, DO NOT waste time in learning the accent.</p>
<p>All you need is good vocabulary, grammar, confidence, and a positive body language to support your speech.</p>
<p><em>When the examiner is speaking, listen to them very carefully without interrupting them and look straight in their eyes so they know that you are actually listening.</em></p>
<h2 id="final-words">Final Words</h2>
<p>In each module, listen/read instructions very very carefully and DON'T try to guess anything. That's the most common mistake and causes a lot of trouble.</p>
<p>I've uploaded some learning material on my Google Drive and made it public. If you have anything that can go there, please share it with me and I'll upload it too. The link to the data is <a target="_blank" href="https://drive.google.com/drive/folders/1uBRqAvecbrtVngg_5ZMYlmUqvLdQkq-R">here</a>.</p>
<blockquote>
<p>I hope you'll find this information helpful and useful. Please share it within your circles so it can benefit more people. Happy learning!!!</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[To err is human!]]></title><description><![CDATA[One thing that I've learned throughout my career is that staying truthful and admitting your mistakes earns you the respect and trust you might not get otherwise.
I have been into situations where I made major mistakes and I could've easily put the b...]]></description><link>https://blog.umairhafeez.com/to-err-is-human</link><guid isPermaLink="true">https://blog.umairhafeez.com/to-err-is-human</guid><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Fri, 28 Aug 2020 00:51:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1598994835805/6Q3qGbgRj.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One thing that I've learned throughout my career is that staying truthful and admitting your mistakes earns you the respect and trust you might not get otherwise.</p>
<p>I have been into situations where I made major mistakes and I could've easily put the blame on someone or something else, but I chose to admit it in front of everyone, and once that time was over, I felt the trust and respect coming my way.</p>
<p>Sometimes, it can be very tough to take in the criticism, you might feel broken inside, but trust me, it's worth it. Take it positively, correct your mistakes, and move on.</p>
<p>On the contrary, if you are on the other side of the table, try to give plenty of room to others to explain and justify themselves. Help them cope with the situation instead of making it worse. Don't forget, today it's them, tomorrow it could be you. No one is perfect!</p>
<p>Learn to admit your mistakes and empathize with others for theirs. At the end of the day, we're all humans!</p>
]]></content:encoded></item><item><title><![CDATA[Angular CDK Coercion: The missing API reference]]></title><description><![CDATA[Let's explore the utilities under @angular/cdk/coercion namespace
Angular is a feature-rich framework that has been globally adopted for small-scale to enterprise-scale web applications. One of the most obvious reasons is the tremendous amount of API...]]></description><link>https://blog.umairhafeez.com/angular-cdk-coercion</link><guid isPermaLink="true">https://blog.umairhafeez.com/angular-cdk-coercion</guid><category><![CDATA[APIs]]></category><category><![CDATA[documentation]]></category><category><![CDATA[Angular]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Tue, 18 Aug 2020 04:32:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1598978305833/K4ktYKDk5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Let's explore the utilities under <code>@angular/cdk/coercion</code> namespace</em></p>
<p>Angular is a feature-rich framework that has been globally adopted for small-scale to enterprise-scale web applications. One of the most obvious reasons is the tremendous amount of APIs and utilities available out of the box to help in everyday development. The core team at Angular has done an amazing job in maintaining &amp; thoroughly documenting everything along with the community contributors, but obviously, there are some patches that are contributed by community and still pending to be documented. In this article, we will explore one of those interesting and quite helpful set of utilities, i.e. <em>Coercion</em>.</p>
<h4 id="what-is-coercion">What is Coercion?</h4>
<p><em>Coercion is the process of implicitly converting data to a required format.</em></p>
<p>There are no hard and fast rules for coercion or implicit type conversion, and may vary from case to case. But our friends at <strong> <a target="_blank" href="https://angular.io/">Angular</a> </strong> and the amazing community got us covered for some basic data types like arrays, booleans, numbers, etc. They’ve built a collection of APIs that can be found under <code>@angular/cdk/coercion</code> namespace.</p>
<p>We'll take a detailed look at these utilities in the following sections. In all the examples, we’ll pass data as <code>@Input</code> properties of our example components and try to coerce the passed values through the coercion APIs, but these APIs can be used anywhere based on your needs.</p>
<h4 id="important"><em>Important:</em></h4>
<p><em>Angular Ivy comes with stricter type checking that can be optionally disabled by using the TypeScript config (<code>tsconfig.json</code>) flags. We’ll see code examples that work with strict type checking enabled as well. You can read more about <code>Angular’s Template type checking</code>  <a target="_blank" href="https://angular.io/guide/template-typecheck">here</a> .</em></p>
<hr />
<h2 id="coercearray">coerceArray</h2>
<blockquote>
<p>export function coerceArray(value: T | T[]): T[]</p>
<p>Wraps the provided value in an array, unless it is an array already</p>
</blockquote>
<p>Consider an example of a component that takes an array of strings and an array of a custom type <code>Person</code> as <code>@Input</code>.</p>
<pre><code><span class="hljs-comment">// array-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { Person } <span class="hljs-keyword">from</span> <span class="hljs-string">'./person.interface'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'array-coercion'</span>,
  template: <span class="hljs-string">`...`</span>
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ArrayCoercionComponent  {
  <span class="hljs-meta">@Input</span>() strings: <span class="hljs-built_in">Array</span>&lt;<span class="hljs-built_in">string</span>&gt;;
  <span class="hljs-meta">@Input</span>() persons: <span class="hljs-built_in">Array</span>&lt;Person&gt;;
}
</code></pre><pre><code><span class="hljs-comment">// person.interface.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Person {
  name: <span class="hljs-built_in">string</span>;
  age: <span class="hljs-built_in">number</span>;
}
</code></pre><p>This is how typically it will be used:</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html  --&gt;</span>

<span class="hljs-comment">&lt;!-- person1 &amp; person2 are objects of type Person  --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">array-coercion</span>
  [<span class="hljs-attr">strings</span>]=<span class="hljs-string">"['array item 1', 'array item 2']"</span>
  [<span class="hljs-attr">persons</span>]=<span class="hljs-string">"[person1, person2]"</span>
&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">array-coercion</span>&gt;</span>
</code></pre><p>It will be nice if we allow passing in a single value and make it work without errors, like this:</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html  --&gt;</span>

<span class="hljs-comment">&lt;!-- person1 is an object of type Person  --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">array-coercion</span>
  [<span class="hljs-attr">strings</span>]=<span class="hljs-string">"'array item 1'"</span>
  [<span class="hljs-attr">persons</span>]=<span class="hljs-string">"person1"</span>
&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">array-coercion</span>&gt;</span>
</code></pre><p>To get this working, we will have to make the following changes to the <code>ArrayCoercionComponent</code>.</p>
<pre><code><span class="hljs-comment">// array-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } from <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { coerceArray } from <span class="hljs-string">'@angular/cdk/coercion'</span>; <span class="hljs-comment">// NEW IMPORT</span>
<span class="hljs-keyword">import</span> { Person } from <span class="hljs-string">'./person.interface'</span>;

<span class="hljs-meta">@Component({
  selector: <span class="hljs-meta-string">'array-coercion'</span>,
  template: `...`
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayCoercionComponent</span>  </span>{
  <span class="hljs-comment">// In the following code, `@Input strings` will NOT work with strict type checking</span>
  <span class="hljs-comment">// But we'll make the `@Input persons` to work with strict type checking as well</span>

  <span class="hljs-comment">// Declare private properties to hold coerced arrays</span>
  <span class="hljs-keyword">private</span> _stringArray: Array&lt;string&gt;;
  <span class="hljs-keyword">private</span> _personArray: Array&lt;Person&gt;;

  <span class="hljs-comment">// We have to separate this getter and name it differently to be used in the template</span>
  <span class="hljs-comment">// This works in combination with the `@Input set persons` defined on line 36</span>
  <span class="hljs-keyword">get</span> coercedPersons(): Array&lt;Person&gt; {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._personArray;
  }

  <span class="hljs-comment">// Use setter to call coerceArray method and convert passed values to arrays</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">get</span> strings(): Array&lt;string&gt; {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._stringArray;
  }
  <span class="hljs-keyword">set</span> strings(<span class="hljs-keyword">val</span>: Array&lt;string&gt;) {
    <span class="hljs-keyword">this</span>._stringArray = coerceArray(<span class="hljs-keyword">val</span>);
  }

  <span class="hljs-comment">// Note that the val parameter excepts a non-array value as well</span>
  <span class="hljs-comment">// We have to do this for strict type checking to work properly</span>
  <span class="hljs-comment">// If we don't do this, following error will be thrown:</span>
  <span class="hljs-comment">// Type 'Person' is not assignable to type 'Person[]'.</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">set</span> persons(<span class="hljs-keyword">val</span>: Person | Array&lt;Person&gt;) {
    <span class="hljs-keyword">this</span>._personArray = coerceArray(<span class="hljs-keyword">val</span>);
  }
}
</code></pre><p><em>Q: What happens if the passed in value is <code>null</code> or <code>undefined</code>?</em></p>
<p> <em>A: It gets wrapped into an array as well, see console log below:</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598990215157/EvyUHuwnY.png" alt="1_3FDpCWkQjSSSRzXdAN3eCA.png" /></p>
<p>You can see, we still get an array but with a single item being <code>null</code> or <code>undefined</code>. I believe this API can be improved in the following ways:</p>
<ol>
<li>If the value is <code>null</code> or <code>undefined</code>, it should not be wrapped in an array, so the consumers can do a simple <em>truthy/falsy</em> check.</li>
<li>Remove all <code>null</code> or <code>undefined</code> items from the array, so to make it clean to be bound without additional <em>truthy/falsy</em> checks on array items.</li>
</ol>
<p>As we have seen in the above examples, using the <code>coerceArray</code> method, we allow the users of our component to pass in an array or a single value without producing any error.</p>
<hr />
<h2 id="coercebooleanproperty">coerceBooleanProperty</h2>
<blockquote>
<p>function coerceBooleanProperty(value: any): boolean</p>
<p>Converts a value (typically a string) to a boolean</p>
</blockquote>
<p>Let’s take an example of a component that takes two boolean flags as <code>@Input</code>.</p>
<pre><code><span class="hljs-comment">// boolean-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } from <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component({
  selector: 'boolean-coercion',
  template: `...`
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BooleanCoercionComponent</span>  </span>{
  <span class="hljs-meta">@Input()</span> flagOne: <span class="hljs-keyword">boolean</span>;
  <span class="hljs-meta">@Input()</span> flagTwo: <span class="hljs-keyword">boolean</span>;
}
</code></pre><p>Example usage of this component will be like the following examples:</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html --&gt;</span>

<span class="hljs-comment">&lt;!-- Bound with class properties --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">boolean-coercion</span>
  [<span class="hljs-attr">flagOne</span>]=<span class="hljs-string">"booleanTrue"</span>
  [<span class="hljs-attr">flagTwo</span>]=<span class="hljs-string">"booleanFalse"</span>
&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">boolean-coercion</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Bound with strings expressions --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">boolean-coercion</span>
  [<span class="hljs-attr">flagOne</span>]=<span class="hljs-string">"'true'"</span>
  [<span class="hljs-attr">flagTwo</span>]=<span class="hljs-string">"'false'"</span>
&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">boolean-coercion</span>&gt;</span>
</code></pre><p>Although these examples show the common way of usage, but as these are booleans, it will be great if we can allow using them like these as well:</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html --&gt;</span>

<span class="hljs-comment">&lt;!-- Input names only, Angular will set the value as empty string ('') --&gt;</span>
<span class="hljs-comment">&lt;!-- Supposed to be truthy --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">boolean-coercion</span> <span class="hljs-attr">flagOne</span> <span class="hljs-attr">flagTwo</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">boolean-coercion</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Strings true/false, without expressions --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">boolean-coercion</span> <span class="hljs-attr">flagOne</span>=<span class="hljs-string">"false"</span> <span class="hljs-attr">flagTwo</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">boolean-coercion</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Random string values, without expressions --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">boolean-coercion</span> <span class="hljs-attr">flagOne</span>=<span class="hljs-string">"random"</span> <span class="hljs-attr">flagTwo</span>=<span class="hljs-string">"random"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">boolean-coercion</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Number, with or without expressions --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">boolean-coercion</span> [<span class="hljs-attr">flagOne</span>]=<span class="hljs-string">"0"</span> <span class="hljs-attr">flagTwo</span>=<span class="hljs-string">"1"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">boolean-coercion</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Some object, null or undefined value --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">boolean-coercion</span> [<span class="hljs-attr">flagOne</span>]=<span class="hljs-string">"person1"</span> [<span class="hljs-attr">flagTwo</span>]=<span class="hljs-string">"nullValue"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">boolean-coercion</span>&gt;</span>
</code></pre><p>Let’s make some changes to our <code>BooleanCoercionComponent</code> to make it work with the above usage examples as well.</p>
<pre><code><span class="hljs-comment">// boolean-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } from <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { coerceBooleanProperty } from <span class="hljs-string">'@angular/cdk/coercion'</span>; <span class="hljs-comment">// NEW IMPORT</span>

<span class="hljs-meta">@Component({
  selector: <span class="hljs-meta-string">'boolean-coercion'</span>,
  template: `...`
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BooleanCoercionComponent</span>  </span>{
  <span class="hljs-comment">// In the following code, `@Input flagOne` will NOT work with strict type checking</span>
  <span class="hljs-comment">// But we'll make the `@Input flagTwo` to work with strict type checking as well</span>

  <span class="hljs-comment">// Declare private properties to hold coerced booleans</span>
  <span class="hljs-keyword">private</span> _flagOne: boolean;
  <span class="hljs-keyword">private</span> _flagTwo: boolean;

  <span class="hljs-comment">// We have to separate this getter and name it differently to be used in the template</span>
  <span class="hljs-comment">// This works in combination with the `@Input set flagTwo` defined on line 36</span>
  <span class="hljs-keyword">get</span> coercedFlagTwo(): boolean {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._flagTwo;
  }

  <span class="hljs-comment">// Use setter to call coerceBooleanProperty method and convert passed values to boolean</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">get</span> flagOne(): boolean {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._flagOne;
  }
  <span class="hljs-keyword">set</span> flagOne(<span class="hljs-keyword">val</span>: boolean) {
    <span class="hljs-keyword">this</span>._flagOne = coerceBooleanProperty(<span class="hljs-keyword">val</span>);
  }

  <span class="hljs-comment">// Note that the val parameter excepts value of type 'any'</span>
  <span class="hljs-comment">// We have to do this for strict type checking to work properly</span>
  <span class="hljs-comment">// If we don't do this, following (or similar) error will be thrown:</span>
  <span class="hljs-comment">// Type 'string' is not assignable to type 'boolean'.</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">set</span> flagTwo(<span class="hljs-keyword">val</span>: any) {
    <span class="hljs-keyword">this</span>._flagTwo = coerceBooleanProperty(<span class="hljs-keyword">val</span>);
  }
}
</code></pre><p><em><strong>Note:</strong> In the strict type checking scenario, we are allowing <code>any</code> value to be passed, the catch here is that if an <code>object</code> is passed as input, it will also be coerced to a boolean. That’s where the component users will have to be careful while passing the inputs to avoid unwanted results.</em></p>
<p>The <code>coerceBooleanProperty</code> utility method is super handy to allow your component users with multiple ways to pass boolean inputs.</p>
<hr />
<h2 id="coercecsspixelvalue">coerceCssPixelValue</h2>
<blockquote>
<p>function coerceCssPixelValue(value: any): string</p>
<p>Coerces a value to a CSS pixel value</p>
</blockquote>
<p>This might be rare, but if you are in a situation where you have a need to pass a CSS pixel value to a component, which might use that value for some inline styling or some other logic, you will have something like this:</p>
<pre><code><span class="hljs-comment">// css-pixel-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } from <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component({
  selector: <span class="hljs-meta-string">'css-pixel-coercion'</span>,
  templateUrl: <span class="hljs-meta-string">'./css-pixel-coercion.component.html'</span>
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CssPixelCoercionComponent</span>  </span>{
  <span class="hljs-meta">@Input()</span> padding: string;
}
</code></pre><pre><code><span class="hljs-comment">&lt;!-- css-pixel-coercion.component.html --&gt;</span>

<span class="hljs-comment">&lt;!-- Using Angular's Style Binding expression --&gt;</span>
<span class="hljs-comment">&lt;!-- The value of 'padding' will have 'px' appended to it --&gt;</span>
<span class="hljs-comment">&lt;!-- But it will be limited only to 'px' and won't allow 'em', 'rem' or '%' --&gt;</span>
<span class="hljs-comment">&lt;!-- Similarly if we do [style.padding.em], it will be limited to 'em' only --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"default"</span> [<span class="hljs-attr">style.padding.px</span>]=<span class="hljs-string">"padding"</span>&gt;</span>
  Hello Coercion, this div has {{ padding }} padding!
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Using Angular's Style Binding expression --&gt;</span>
<span class="hljs-comment">&lt;!-- We don't use the unit expression, and leave it open for any value to be passed --&gt;</span>
<span class="hljs-comment">&lt;!-- We can do similar to above example using a custom conversion method --&gt;</span>
<span class="hljs-comment">&lt;!-- But again, we will limit to a certain unit, e.g. 'px' or 'em' --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"default"</span> [<span class="hljs-attr">style.padding</span>]=<span class="hljs-string">"padding"</span>&gt;</span>
  Hello Coercion, this div has {{ padding }} padding!
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre><p>The example usage of the above component will be the following:</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html --&gt;</span>

<span class="hljs-comment">&lt;!-- This will work if we have [style.padding.px] --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">css-pixel-coercion</span> [<span class="hljs-attr">padding</span>]=<span class="hljs-string">"10"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">css-pixel-coercion</span>&gt;</span>

<span class="hljs-comment">&lt;!-- This will work if we have [style.padding] --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">css-pixel-coercion</span> [<span class="hljs-attr">padding</span>]=<span class="hljs-string">"'10px'"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">css-pixel-coercion</span>&gt;</span>
</code></pre><p>It will be more intuitive if we allow the users of our component to pass in number, pixel value, em, or a value with any other valid unit. Examples of such usage can be like this:</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html --&gt;</span>

<span class="hljs-comment">&lt;!-- This gets converted as 10px --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">css-pixel-coercion</span> [<span class="hljs-attr">padding</span>]=<span class="hljs-string">"10"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">css-pixel-coercion</span>&gt;</span>

<span class="hljs-comment">&lt;!-- The following strings get bound as-is --&gt;</span>
<span class="hljs-comment">&lt;!-- The component users can pass in values with other units as well --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">css-pixel-coercion</span> [<span class="hljs-attr">padding</span>]=<span class="hljs-string">"'10px'"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">css-pixel-coercion</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">css-pixel-coercion</span> [<span class="hljs-attr">padding</span>]=<span class="hljs-string">"'1em'"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">css-pixel-coercion</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">css-pixel-coercion</span> [<span class="hljs-attr">padding</span>]=<span class="hljs-string">"'1rem'"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">css-pixel-coercion</span>&gt;</span>
</code></pre><p>To make this work, let’s see how our <code>CssPixelCoercionComponent</code> will look like.</p>
<pre><code><span class="hljs-comment">// css-pixel-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } from <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { coerceCssPixelValue } from <span class="hljs-string">'@angular/cdk/coercion'</span>; <span class="hljs-comment">// NEW IMPORT</span>

<span class="hljs-meta">@Component({
  selector: <span class="hljs-meta-string">'css-pixel-coercion'</span>,
  template: `...`
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CssPixelCoercionComponent</span>  </span>{
  <span class="hljs-comment">// In the following code, `@Input paddingX` will NOT work with strict type checking</span>
  <span class="hljs-comment">// But we'll make the `@Input paddingY` to work with strict type checking as well</span>

  <span class="hljs-comment">// Declare private properties to hold coerced booleans</span>
  <span class="hljs-keyword">private</span> _paddingX: string;
  <span class="hljs-keyword">private</span> _paddingY: string;

  <span class="hljs-comment">// We have to separate this getter and name it differently to be used in the template</span>
  <span class="hljs-comment">// This works in combination with the `@Input set paddingY` defined on line 36</span>
  <span class="hljs-keyword">get</span> coercedPaddingY(): string {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._paddingY;
  }

  <span class="hljs-comment">// Use setter to call coerceCssPixelValue method and convert passed values to pixel string</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">get</span> paddingX(): string {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._paddingX;
  }
  <span class="hljs-keyword">set</span> paddingX(<span class="hljs-keyword">val</span>: string) {
    <span class="hljs-keyword">this</span>._paddingX = coerceCssPixelValue(<span class="hljs-keyword">val</span>);
  }

  <span class="hljs-comment">// Note that the val parameter excepts value of type 'number | string'</span>
  <span class="hljs-comment">// We have to do this for strict type checking to work properly</span>
  <span class="hljs-comment">// If we don't do this, following error will be thrown:</span>
  <span class="hljs-comment">// Type 'number' is not assignable to type 'string'.</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">set</span> paddingY(<span class="hljs-keyword">val</span>: number | string) { <span class="hljs-comment">// [A] More details below</span>
    <span class="hljs-keyword">this</span>._paddingY = coerceCssPixelValue(<span class="hljs-keyword">val</span>);
  }
}
</code></pre><p><code>[A]</code>: As we saw that the <code>coerceCssPixelValue</code> method takes the value parameter of type <code>any</code> which means we could’ve written the setter as:</p>
<p><code>set paddingY(val: any)</code></p>
<p>But we restricted it only to pass in <code>number</code> or <code>string</code> only. The reason was that, if the user passes <code>null</code> or <code>undefined</code>, it would be converted to empty strings and if an <code>object</code> gets passed, it would be stringified as <code>[object Object]px</code>. So, we restricted the input but kept the flexibility to pass valid, usable values.</p>
<hr />
<h2 id="coerceelement">coerceElement</h2>
<blockquote>
<p>function coerceElement(elementOrRef: ElementRef | T): T</p>
<p>Coerces an ElementRef into an Element, unless it is already an Element</p>
</blockquote>
<p>At times, we might need a component to accept a native HTML element as an input of our component and add some functionality around it. An example component might look something like this:</p>
<pre><code><span class="hljs-comment">// element-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } from <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component({
  selector: <span class="hljs-meta-string">'element-coercion'</span>,
  template: `...`
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElementCoercionComponent</span>  </span>{
  <span class="hljs-meta">@Input()</span> elementOne: Element;
  <span class="hljs-meta">@Input()</span> elementTwo: Element;
}
</code></pre><p>Working with Angular, we make use of <code>ElementRef</code> wrapper very frequently, and we might want to allow passing in <code>ElementRef</code> to our component. So we can change the input as:</p>
<pre><code><span class="hljs-comment">// element-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, ElementRef, Input } from <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component({
  selector: <span class="hljs-meta-string">'element-coercion'</span>,
  template: `...`
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElementCoercionComponent</span>  </span>{
  <span class="hljs-meta">@Input()</span> elementOne: Element | ElementRef;
  <span class="hljs-meta">@Input()</span> elementTwo: Element | ElementRef;
}
</code></pre><p>Now, we can pass in native <code>HTMLElement</code> or <code>ElementRef</code>, as in the following example.</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html --&gt;</span>

<span class="hljs-comment">&lt;!-- Assuming that 'htmlElement' is a class property that returns a native HTML element --&gt;</span>
<span class="hljs-comment">&lt;!-- Assuming that 'elementRef' is a class property that returns an instance of ElementRef --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">element-coercion</span>
  [<span class="hljs-attr">elementOne</span>]=<span class="hljs-string">"htmlElement"</span>
  [<span class="hljs-attr">elementTwo</span>]=<span class="hljs-string">"elementRef"</span>
&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">element-coercion</span>&gt;</span>
</code></pre><p>So far so good! But, in our <code>ElementCoercionComponent</code>, we needed only native HTML element. This is where we can make use of the <code>coerceElement</code> utility function, and change our component to look like this:</p>
<pre><code><span class="hljs-comment">// element-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, ElementRef, Input } from <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { coerceElement } from <span class="hljs-string">'@angular/cdk/coercion'</span>; <span class="hljs-comment">// NEW IMPORT</span>

<span class="hljs-meta">@Component({
  selector: <span class="hljs-meta-string">'element-coercion'</span>,
  template: ``
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElementCoercionComponent</span>  </span>{
  <span class="hljs-comment">// In the following code, `@Input elementOne` will NOT work with strict type checking</span>
  <span class="hljs-comment">// But we'll make the `@Input elementTwo` to work with strict type checking as well</span>

  <span class="hljs-comment">// Declare private properties to hold coerced elements</span>
  <span class="hljs-keyword">private</span> _elementOne: Element;
  <span class="hljs-keyword">private</span> _elementTwo: Element;

  <span class="hljs-comment">// We have to separate this getter and name it differently to be used in the template</span>
  <span class="hljs-comment">// This works in combination with the `@Input set elementTwo` defined on line 36</span>
  <span class="hljs-keyword">get</span> coercedElementTwo(): Element {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._elementTwo;
  }

  <span class="hljs-comment">// Use setter to call coerceElement method and convert passed value to Element</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">get</span> elementOne(): Element {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._elementOne;
  }
  <span class="hljs-keyword">set</span> elementOne(<span class="hljs-keyword">val</span>: Element) {
    <span class="hljs-keyword">this</span>._elementOne = coerceElement(<span class="hljs-keyword">val</span>);
  }

  <span class="hljs-comment">// Note that the val parameter excepts value of type 'Element | ElementRef'</span>
  <span class="hljs-comment">// We have to do this for strict type checking to work properly</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">set</span> elementTwo(<span class="hljs-keyword">val</span>: Element | ElementRef) {
    <span class="hljs-keyword">this</span>._elementTwo = coerceElement(<span class="hljs-keyword">val</span>);
  }
}
</code></pre><p>Sweet, right?</p>
<hr />
<h2 id="coercenumberproperty">coerceNumberProperty</h2>
<blockquote>
<p>function coerceNumberProperty(value: any, fallbackValue = 0): number</p>
<p>Coerces a data-bound value (typically a string) to a number</p>
</blockquote>
<p>Passing numbers as component inputs or function arguments is another very common practice. Let’s suppose we have a component that takes two numbers as input.</p>
<pre><code><span class="hljs-comment">// number-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'number-coercion'</span>,
  template: <span class="hljs-string">`...`</span>
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> NumberCoercionComponent  {
  <span class="hljs-meta">@Input</span>() numberOne: <span class="hljs-built_in">number</span>;
  <span class="hljs-meta">@Input</span>() numberTwo: <span class="hljs-built_in">number</span>;
}
</code></pre><p>Example usage of this component can be something like this:</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html --&gt;</span>

<span class="hljs-comment">&lt;!-- Expression with a number value or a class property --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">number-coercion</span> [<span class="hljs-attr">numberOne</span>]=<span class="hljs-string">"10"</span> [<span class="hljs-attr">numberTwo</span>]=<span class="hljs-string">"numericValue"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">number-coercion</span>&gt;</span>
</code></pre><p>It would be great if we can allow the following usage as well:</p>
<pre><code><span class="hljs-comment">&lt;!-- app.component.html --&gt;</span>

<span class="hljs-comment">&lt;!-- Inline string value or an expression with a string value --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">number-coercion</span> <span class="hljs-attr">numberOne</span>=<span class="hljs-string">"10"</span> [<span class="hljs-attr">numberTwo</span>]=<span class="hljs-string">"stringValue"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">number-coercion</span>&gt;</span>
</code></pre><p>The input value can also be <code>null</code> or <code>undefined</code> and could cause unwanted situations or runtime errors. Let’s make some changes to our <code>NumberCoercionComponent</code> to make sure that the input values are always valid numbers after we receive them.</p>
<pre><code><span class="hljs-comment">// number-coercion.component.ts</span>

<span class="hljs-keyword">import</span> { Component, Input } from <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { coerceNumberProperty } from <span class="hljs-string">'@angular/cdk/coercion'</span>; <span class="hljs-comment">// NEW IMPORT</span>

<span class="hljs-meta">@Component({
  selector: <span class="hljs-meta-string">'number-coercion'</span>,
  template: `...`
})</span>
export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NumberCoercionComponent</span>  </span>{
  <span class="hljs-comment">// In the following code, `@Input numberOne` will NOT work with strict type checking</span>
  <span class="hljs-comment">// But we'll make the `@Input numberTwo` to work with strict type checking as well</span>

  <span class="hljs-comment">// Declare private properties to hold coerced numbers</span>
  <span class="hljs-keyword">private</span> _numberOne: number;
  <span class="hljs-keyword">private</span> _numberTwo: number;

  <span class="hljs-comment">// We have to separate this getter and name it differently to be used in the template</span>
  <span class="hljs-comment">// This works in combination with the `@Input set numberTwo` defined on line 36</span>
  <span class="hljs-keyword">get</span> coercedNumberTwo(): number {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._numberTwo;
  }

  <span class="hljs-comment">// Use setter to call coerceNumberProperty method and convert passed value to number</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">get</span> numberOne(): number {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._numberOne;
  }
  <span class="hljs-keyword">set</span> numberOne(<span class="hljs-keyword">val</span>: number) {
    <span class="hljs-keyword">this</span>._numberOne = coerceNumberProperty(<span class="hljs-keyword">val</span>);
  }

  <span class="hljs-comment">// Note that the val parameter excepts value of type 'any'</span>
  <span class="hljs-comment">// We have to do this for strict type checking to work properly</span>
  <span class="hljs-comment">// 'coerceNumberProperty' method takes a second parameter</span>
  <span class="hljs-comment">// The second parameter is the fallback or default value</span>
  <span class="hljs-meta">@Input()</span>
  <span class="hljs-keyword">set</span> numberTwo(<span class="hljs-keyword">val</span>: any) {
    <span class="hljs-keyword">this</span>._numberTwo = coerceNumberProperty(<span class="hljs-keyword">val</span>, <span class="hljs-number">12</span>);
  }
}
</code></pre><p>There you go!</p>
<hr />
<h2 id="conclusion">Conclusion</h2>
<p>In the sections above, we saw how these small utilities help us make sure that our component inputs receive the data gracefully with some level of flexibility.</p>
<p>Although this is a small list of utilities, I am sure we can make improvements to the existing ones and add more to this list for the amazing community. I would recommend you to take a look at the implementation of these APIs  <a target="_blank" href="https://github.com/angular/components/tree/master/src/cdk/coercion">here</a> .</p>
<p>Looking forward to hearing your thoughts and feedback. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Building a successful team: Role of a Lead]]></title><description><![CDATA[A lot has been written and talked about leadership in general but in this post, I want to talk about something very opinionated, something that I have learned over the years.
It was in 2015 when I got my first opportunity to lead a team of 5 people, ...]]></description><link>https://blog.umairhafeez.com/building-a-successful-team-role-of-a-lead</link><guid isPermaLink="true">https://blog.umairhafeez.com/building-a-successful-team-role-of-a-lead</guid><category><![CDATA[team]]></category><category><![CDATA[leadership]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Mon, 29 Jun 2020 01:31:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1598578433862/9_ma7Cc_v.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>A lot has been written and talked about leadership in general but in this post, I want to talk about something very opinionated, something that I have learned over the years.</em></p>
<p>It was in 2015 when I got my first opportunity to lead a team of 5 people, where we had to build a product from the ground up. In my next 2 roles, I was lucky enough to get the same opportunity again, i.e. building a team and delivering critical projects.</p>
<p>Not to brag, but I have been always lucky to be blessed with the most amazing people around me, and WE managed to build the best teams with best results, teams that were cohesive, motivated, and successful.</p>
<hr />
<h2 id="what-did-i-do-in-my-role-as-a-lead">What did I do in my role as a Lead?</h2>
<p>The answer to this question is not a short one. I learned my lessons over time, trying different approaches, from time to time, day over day.</p>
<blockquote>
<p><strong>Spoiler Alert:</strong> There is absolutely nothing technical!</p>
</blockquote>
<p>I took my time to validate these simple but effective approaches before bringing them to you. I made a checklist that can be easily referred to, and you can selectively pick or mix &amp; match any of these based on the situation.</p>
<p><em>Here you go!</em></p>
<p>★ Be an example of how you want to see your team</p>
<p>★ Respect everyone equally, this is THE MOST IMPORTANT thing</p>
<p>★ No matter how stressed you are in your personal life, it should NOT reflect at work</p>
<p>★ Humans make mistakes! If someday, it’s one of your team members, don’t embarrass them, don’t hurt their self-respect, and don’t leave them alone to fix it</p>
<p>★ Everyone has a different personality, try best to understand everyone in your team and don’t let any biases occupy your mind</p>
<p>★ Learn from others, everyone knows something you don’t know</p>
<p>★ Share what you know, even general life experiences</p>
<p>★ Try to know the skills of every individual in your team and what everyone is really good and comfortable at</p>
<p>★ Gossip about non-work matters occasionally</p>
<p>★ Plan some recreational activity (game, dinner, etc) at least once a month, be it inside or outside of work premises</p>
<p>★ Make sure to check on their health and that of their loved ones</p>
<p>★ Appreciate frequently even the smallest of things</p>
<p>★ Talk about their future goals and put your best effort to help achieve those goals</p>
<p>★ Build a sense of ownership about work and tasks in hand and make sure everyone gets their due credit of every single contribution</p>
<p>★ Start your day by visiting everyone individually, maybe only 5 minutes, talk about work and inquire if they have any issues or impediments, resolve them as early as possible</p>
<p>★ Encourage and empower everyone by giving them responsibilities, start with small if they’re hesitant</p>
<p>★ Stress and crunch times are common, handling them is the real challenge</p>
<ul>
<li>★ Make sure that everyone is assigned to what they are good at</li>
<li>★ Try to help them prioritize and deliver their tasks</li>
<li>★ Be the helping hand they need, sit with them if they’re stuck</li>
</ul>
<p>★ Conflicts are natural and can happen internally within the team, cross-functional team members and some times between team members and management</p>
<ul>
<li>★ Listen!!! Listen to both sides of the story before even thinking of a decision</li>
<li>★ Be a diplomat and don’t take sides unless one side is clearly wrong, but more inclination should be towards your team and their benefits</li>
<li>★ Don’t bring conflicts to public attention, keep them secret</li>
<li>★ Don’t let conflicts change your opinions about either side</li>
<li>★ Prevent heated arguments, make sure to realize that at the end of the day, it is just a job</li>
</ul>
<p>★ Trouble makers, problem child type, and negative people are inevitable</p>
<ul>
<li>★ Identify them sooner than later</li>
<li>★ Keep your eyes and ears open</li>
<li>★ If they are infecting the team, try to intervene without exposing your intentions</li>
<li>★ If you see behavioral changes in your good people, talk to them and win their confidence back and ask them if they need any help</li>
<li>★ As soon as you notice things getting out of control, engage HR, and make sure that the situation gets handled positively without injustice to anyone</li>
</ul>
<hr />
<p>Most of these might not be new for you, but I am sure that having them listed at one consolidated place will help. Last but not the least, I want to say:</p>
<blockquote>
<p>Reward!!! “What gets rewarded, gets repeated”</p>
</blockquote>
<p>In the end, I would like to thank you for reading. Please share your thoughts and experiences on the topic. I would love to hear and learn!</p>
]]></content:encoded></item><item><title><![CDATA[Angular: Dependency Injection and the function of Injectors & Providers]]></title><description><![CDATA[Dependency is the reliance of one thing on another, to perform its tasks. In everyday life, we depend on so many things to complete our routine work. Those dependencies have to be available before we start our work, in order to start and complete it ...]]></description><link>https://blog.umairhafeez.com/angular-dependency-injection-and-the-function-of-injectors-and-providers</link><guid isPermaLink="true">https://blog.umairhafeez.com/angular-dependency-injection-and-the-function-of-injectors-and-providers</guid><category><![CDATA[Angular]]></category><category><![CDATA[dependency injection]]></category><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Wed, 24 Jun 2020 22:33:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1599000421508/5ob6Z4P9A.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Dependency is the reliance of one thing on another, to perform its tasks. In everyday life, we depend on so many things to complete our routine work. Those dependencies have to be available before we start our work, in order to start and complete it on time.</p>
<p>Similar types of dependencies exist in the software engineering world, and those dependencies have to be made available by some mechanism generally called Dependency Injection, and that is what I’d like to discuss today.</p>
<h2 id="what-is-dependency-injection">What is Dependency Injection?</h2>
<p>Dependency Injection or DI is generally thought to be a very complex topic, but in truth, it’s quite simple and easy to understand, even if you’re five, as this example illustrates:</p>
<blockquote>
<p>How to explain dependency injection to a 5-year-old?</p>
<p>When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something  Mommy or Daddy doesn’t want you to &gt; have. You might even be looking for something we don’t even have or which has expired.</p>
<p>What you should be doing is stating a need, “I need something to drink with lunch,” and then we will make sure you have something when you sit down to eat.</p>
<p>Source:  <a target="_blank" href="https://stackoverflow.com/a/1638961/1063624">StackOverflow</a> </p>
</blockquote>
<p>DI is a technique under the <a target="_blank" href="https://en.wikipedia.org/wiki/Inversion_of_control">Inversion of Control</a> (IoC) principle/pattern. In this mechanism, a centralized object is made responsible for providing all the services or things on which our application blocks depend. The application blocks define the list of services or items they need, and they don’t have to worry about how to construct or instantiate those services and how to dispose of them if they’re no longer required.</p>
<h2 id="angulars-implementation-of-di">Angular’s Implementation of DI</h2>
<p>In the Angular framework, DI is one of the core mechanisms, taking care of instantiating and loading dependencies for all components, directives, and services.</p>
<p>Angular automatically creates a centralized Injector that is loaded when the application bootstraps. The injector looks for all defined dependencies and maintains instances that can be reused, inside a container, generally referred to as DI Container.</p>
<p>But how does the injector know how to load or create an instance of a dependency? Angular has something called Provider, which <em>“provides”</em> that information to the injector. When you require a dependency, be it a service, function, or value in your application, you have to register a provider in the application injector. The injector will then use that registered information to instantiate and load the dependency whenever it is required.</p>
<pre><code><span class="hljs-keyword">import</span> { AppService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.service'</span>;

<span class="hljs-meta">@Component</span>({
 selector: <span class="hljs-string">'app-component'</span>,
 templateUrl: <span class="hljs-string">'./app.component.html'</span>,
 providers: [ AppService ]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppComponent {
 <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> appService: AppService</span>) {}
}
</code></pre><p><em><code>A component that depends on a service named AppService</code></em></p>
<p>Considering the constructor here, as soon as code reaches a point to instantiate this component class, it informs Angular about the dependency. The Angular process checks if the injector has an existing instance of the dependency. The injector looks for an existing instance in its container and creates one if not, and finally returns the instance to Angular by keeping a reference in the container.</p>
<blockquote>
<p><strong>Note:</strong> The type of dependency is NOT optional, you have to tell Angular about the object type so it can create its instance when needed. In this example, it’s the <code>AppService</code> type.</p>
</blockquote>
<p>In this example, we have only one dependency, whereas, in practice, it can be more. When Angular finally receives the instances of all the dependencies from the injector, it then calls the constructor with those service instances as arguments, of course, in the same sequence.</p>
<p>There is a small caveat in this example; we provided the service reference to Angular using the component's providers' collection. If we use this approach, we are telling Angular to get a new instance of the <code>AppService</code> for each instance of the component. But that probably isn't what we needed, right?</p>
<h2 id="hierarchical-injector">Hierarchical Injector</h2>
<p>The Angular’s root or centralized injector is a hierarchical injector, which is one of its most exciting features. </p>
<p>It means if we provide a service for one module or component, the instance of that service will be available to all the descendants of that module or component. In an Angular application, there are multiple places where we can “provide” a service:</p>
<p><strong>AppModule:</strong> If we provide a service at this level, it will act as a Singleton service, i.e., one instance for the whole application, unless we override this for a sub-module or component.</p>
<p><strong>AnyOtherSubModule:</strong> If we provide services at this level, Angular will create a child injector automatically, which will inherit from the parent injector. This child injector will be responsible for maintaining instances of the services provided for this module and all its children (modules, components, directives, services, etc.) unless we override this in a sub-module or component.</p>
<p><strong>AppComponent:</strong> Providing a service at this level means one instance of service is available for AppComponent and all its children, but not other services or <code>AppModule</code>. Angular will again create a child injector inherited from the parent injector to maintain instances of services at the AppComponent level.</p>
<p><strong>AnyOtherSubComponent:</strong> As in the example above, one instance of service will be available for one set of instances of this component and it’s children (if they exist). This will also be handled by an automatically created child injector for each instance of the component.</p>
<blockquote>
<p><strong>Note:</strong> None of these patterns are wrong. It will vary depending on the application needs and whether you want one Singleton instance of a service or you want separate instances of the service for each component and its descendants.</p>
</blockquote>
<p>In real-world applications, most of them will have child injectors being created by Angular to manage service instances and provide them whenever needed. Since Angular creates these child injectors automatically, Angular handles all the clean up as well when those child injectors are no longer required.</p>
<h2 id="the-injectable-decorator">The <code>@Injectable</code> Decorator</h2>
<p>We’ve talked about injecting services into components, directives, and pipes, etc., but haven’t talked about injecting services into services. Look at the example below and guess if it has an error:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> LoggingService {
 <span class="hljs-keyword">private</span> _logItems: <span class="hljs-built_in">Array</span>&lt;{
   action: <span class="hljs-built_in">string</span>,
   counter: <span class="hljs-built_in">number</span>
 }&gt; = [];

 <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {}

 log(action: <span class="hljs-built_in">string</span>, counter: <span class="hljs-built_in">number</span>) {
   <span class="hljs-built_in">this</span>._logItems.push({action, counter});
 }
}
</code></pre><p><em><code>LoggingService: A simple class that maintains a collection of log items</code></em></p>
<pre><code><span class="hljs-keyword">import</span> { LoggingService } from <span class="hljs-string">'./logging.service'</span>;

export <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CounterService</span> </span>{
 counter = <span class="hljs-number">0</span>;

 <span class="hljs-keyword">constructor</span>(<span class="hljs-keyword">private</span> loggingService: LoggingService) {}

 increment() {
   <span class="hljs-keyword">this</span>.counter++;
   <span class="hljs-keyword">this</span>.loggingService.log(<span class="hljs-string">'increment'</span>, <span class="hljs-keyword">this</span>.counter);
 }

 decrement() {
   <span class="hljs-keyword">this</span>.counter--;
   <span class="hljs-keyword">this</span>.loggingService.log(<span class="hljs-string">'decrement'</span>, <span class="hljs-keyword">this</span>.counter);
 }
}
</code></pre><p><em><code>CounterService: Another class with a few methods, and depends on the LoggingService class</code></em></p>
<pre><code><span class="hljs-keyword">@NgModule</span>({
 <span class="hljs-selector-tag">imports</span>: <span class="hljs-selector-attr">[ BrowserModule ]</span>,
 <span class="hljs-selector-tag">declarations</span>: <span class="hljs-selector-attr">[ AppComponent ]</span>,
 <span class="hljs-selector-tag">providers</span>: <span class="hljs-selector-attr">[ CounterService, LoggingService ]</span>,
 <span class="hljs-selector-tag">bootstrap</span>: <span class="hljs-selector-attr">[ AppComponent ]</span>
})
<span class="hljs-selector-tag">export</span> <span class="hljs-selector-tag">class</span> <span class="hljs-selector-tag">AppModule</span> {}
</code></pre><p><em><code>AppModule: @NgModule with both services declared above listed in the 'provider's' collection</code></em></p>
<p>There is a problem in the example above and Angular will report an error similar to the one below:</p>
<blockquote>
<p>The class ‘CounterService’ cannot be created via dependency injection, as it does not have an Angular decorator. This will result in an error at runtime.</p>
<p>Either add the <code>@Injectable()</code> decorator to ‘CounterService’, or configure a different provider (such as a provider with ‘useFactory’).</p>
</blockquote>
<p>This is a very common misconception about the <code>@Injectable</code> decorator. Since the <code>CounterService</code> depends on the <code>LoggingService</code>, we have to tell Angular that <code>CounterService</code> is “injectable”, which means it depends on some other service and that other service will be injected “into” this service. So we have to add the <code>@Injectable</code> decorator before the <code>CounterService</code> declaration like below. </p>
<p>The important thing to note here is that no error was reported for <code>LoggingService</code> because it doesn’t depend on anything for instantiation. </p>
<blockquote>
<p>For the sake of performance, consistency, and avoiding any future errors, it’s a best practice to add <code>@Injectable</code> decorator to all service classes. For instance, if we decide to inject some dependency in the <code>LoggingService</code> in the future and forget the <code>@Injectable</code> decorator, Angular will throw the same error.</p>
</blockquote>
<p>To fix the above error, simply add the <code>@Injectable</code> decorator to the <code>CounterService</code> class.</p>
<pre><code><span class="hljs-keyword">import</span> { Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { LoggingService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./logging.service'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CounterService {
 counter = <span class="hljs-number">0</span>;

 <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> loggingService: LoggingService</span>) {}
}
</code></pre><p><em><code>CounterService with @Injectable decorator</code></em></p>
<h2 id="the-super-power-of-the-injectable-decorator">The Super Power of the <code>@Injectable</code> Decorator</h2>
<p>The amazing <code>@Injectable</code> decorator has another fascinating usage. We can use it to provide a service at the root injector level, which makes this service globally accessible to all modules, services, components, pipes, etc. No matter where your service resides in the code, you can make it globally accessible by passing in a special object to the <code>@Injectable</code> decorator like below:</p>
<pre><code><span class="hljs-variable">@Injectable</span>({
 <span class="hljs-attribute">providedIn</span>: <span class="hljs-string">'root'</span>
})
</code></pre><p><em><code>@Injectable decorator with config to provide service for root injector</code></em></p>
<p>Voila! Our service is now globally accessible and can be injected into other modules, services, and components without providing it anywhere else. <strong>And one very important benefit that we get here is that our service is now fully tree-shakable.</strong> 🙌🏼</p>
<p>By default, Angular CLI generates services with this pattern and recommends having <code>@Injectable</code> decorator being added to all the services. As mentioned earlier, it’s a best practice to have it with all service classes, but it is up to the application requirements and use cases to choose for other available options and patterns.</p>
<p>As of Angular 9, the Angular team introduced two more value options for the <code>providedIn</code> property, listed below:</p>
<p><strong>'platform':</strong> Since we can have multiple Angular applications running on one page, for instance, if you have a micro frontend architecture,  you can share services across applications using this value.</p>
<p><strong>'any':</strong> Use this value to instruct Angular to create a global instance of this service for all eagerly loaded modules, and a separate instance of this service for all lazy-loaded modules that inject it.</p>
<h2 id="take-away">Take Away</h2>
<p>In this article, we saw how Dependency Injection works in an Angular application and how we can utilize the injectors and providers to get instances of our services based on our requirements. However, this topic is broad and I have only skimmed the surface. But I hope that my simplistic approach was able to provide you with a broad understanding of Angular DI and inspired you to consider it for your next development.</p>
<p>The example code for this article is attached for download  <a target="_blank" href="https://drive.google.com/open?id=1gdKzgb-C3CcJ8OP2xAkpkEEhShun4SFe">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Workplace Harmony]]></title><description><![CDATA[Professional life is very interesting! You come across people from diverse backgrounds, ethnicities, cultures, religions, and regions. Everyone has a different way of thinking, talking, communicating, perceiving, and working.
When working in such a h...]]></description><link>https://blog.umairhafeez.com/workplace-harmony</link><guid isPermaLink="true">https://blog.umairhafeez.com/workplace-harmony</guid><dc:creator><![CDATA[Umair Hafeez]]></dc:creator><pubDate>Sat, 30 May 2020 00:52:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1598576223444/Vupnz5KGq.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Professional life is very interesting! You come across people from diverse backgrounds, ethnicities, cultures, religions, and regions. Everyone has a different way of thinking, talking, communicating, perceiving, and working.</p>
<p>When working in such a heterogeneous environment, it's very common, rather inevitable, to have conflicts and arguments over so many various matters. Mostly it's because of the aforementioned differences as all those attributes mold our personality. Also, for some people, some days are just different. We're all humans, and we have personal lives and personal matters, which affect our day to day personality as well.</p>
<p>If we realize and understand these facts, we can very easily avoid workplace conflicts and stress, most of the time, if not every time. By keeping all these realities in mind, we should:</p>
<ol>
<li>Practice empathy before judging and jumping to conclusions</li>
<li>Try to listen and absorb the other person's point of view</li>
<li>Think with different angles, if possible</li>
<li>Try to put yourself in the other person's shoes</li>
</ol>
<p>Another interesting theory I have is, that we should try to build a Professional Personality, which might be different from what our real personality is. For instance, someone might be an introvert or a shy person, which is natural, but that doesn't help much in professional life. They have to be vocal and good in communication while at work, which is kind of going against their personality, but it is really very important.</p>
<p>Workplace harmony is critical for any organization and more so for every professional to do their job peacefully. We should all learn to compliment each other in a positive way as good humans.</p>
<p>I would love to hear your thoughts!</p>
]]></content:encoded></item></channel></rss>