<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adam Barker</title>
    <description>The latest articles on DEV Community by Adam Barker (@_adam_barker).</description>
    <link>https://dev.to/_adam_barker</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F54541%2F435c9971-729e-471b-9703-ae11d784646f.jpg</url>
      <title>DEV Community: Adam Barker</title>
      <link>https://dev.to/_adam_barker</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_adam_barker"/>
    <language>en</language>
    <item>
      <title>How to make a dynamic Twitter Header with Switchboard Canvas</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Wed, 27 Oct 2021 13:57:41 +0000</pubDate>
      <link>https://dev.to/_adam_barker/how-to-make-a-dynamic-twitter-header-with-switchboard-canvas-1flk</link>
      <guid>https://dev.to/_adam_barker/how-to-make-a-dynamic-twitter-header-with-switchboard-canvas-1flk</guid>
      <description>&lt;p&gt;A &lt;a href="https://dev.to/dailydevtips1/how-i-made-my-twitter-header-dynamic-68d"&gt;number&lt;/a&gt; &lt;a href="https://dev.to/haideralipunjabi/dynamic-twitter-header-using-python-4hkm"&gt;of&lt;/a&gt; &lt;a href="https://dev.to/erikaheidi/how-to-dynamically-update-twitter-cover-image-to-show-latest-followers-using-php-gd-and-twitteroauth-62n"&gt;interesting posts&lt;/a&gt; here on dev.to describe how to make a dynamic Twitter header/cover and they inspired me to add this capability to Switchboard Canvas - an API-driven image generation tool.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://www.switchboard.ai"&gt;Switchboard Canvas&lt;/a&gt;, users first create a template, then use the API to create images from it with data you supply or from other tools that you already use.&lt;/p&gt;

&lt;p&gt;In this tutorial we’ll:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a template&lt;/li&gt;
&lt;li&gt;Use Switchboard Canvas to make a connection to Twitter&lt;/li&gt;
&lt;li&gt;Use the API to generate an image from the template&lt;/li&gt;
&lt;li&gt;Use the API to actually update your Twitter header&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What are the dimensions of a Twitter header/cover image?
&lt;/h3&gt;

&lt;p&gt;The correct size for a Twitter header/cover image is 1500x500 pixels. &lt;/p&gt;

&lt;h3&gt;
  
  
  Making a Twitter header/cover template
&lt;/h3&gt;

&lt;p&gt;Open the Previewer and choose Profile header from the Twitter section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0auXGb6Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/twitter-cover-size.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0auXGb6Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/twitter-cover-size.png" alt="Twitter Cover in the Switchboard Canvas Palette" width="612" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Saving your template at this point, despite it being empty, will default it to this size in the future.&lt;/p&gt;

&lt;h4&gt;
  
  
  Background
&lt;/h4&gt;

&lt;p&gt;For a background, I chose this moon and stars backdrop from Adobe Stock. I also resized it to a height of 500px. Upload the resulting image to your Library.&lt;/p&gt;

&lt;p&gt;Add an Image element choose the image from your Library. Make sure the API name for the image is &lt;code&gt;backdrop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RiC3ugpe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/adobe-stock-preview.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RiC3ugpe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/adobe-stock-preview.png" alt="Adobe Stock Preview" width="880" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l9yol7RS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/backdrop-in-place.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l9yol7RS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/backdrop-in-place.png" alt="Starry sky backdrop in place" width="880" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When choosing a background for a template, it’s helpful to have it fade into another color, especially if you’re going to add Text elements on top of the image.&lt;/p&gt;

&lt;p&gt;In the template properties, set the background color to &lt;code&gt;#112346&lt;/code&gt;: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kuIHbjRG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/template-background-color.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kuIHbjRG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/template-background-color.png" alt="The template's background color" width="730" height="942"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can change the Element Opacity of the background image to something around the 75% mark:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w6en69Fi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/element-opacity.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w6en69Fi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/element-opacity.png" alt="Setting the background image's opacity" width="714" height="172"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Adding a quote element
&lt;/h4&gt;

&lt;p&gt;To add a quote to the image, we’re going to add a Text element. I’m using a Google Font called Sorts Mill Goudy from Google: &lt;a href="https://fonts.google.com/specimen/Sorts+Mill+Goudy"&gt;https://fonts.google.com/specimen/Sorts+Mill+Goudy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using pinning, we’re going to ensure that regardless of the quote we use in the Text element, it will stay centered, and won’t take up any more room than the bounding box.&lt;/p&gt;

&lt;p&gt;Follow these steps to create and position the Text element for your quote:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;code&gt;Add Text&lt;/code&gt; or press &lt;code&gt;T&lt;/code&gt; to add a Text element.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;API Name&lt;/code&gt; to &lt;code&gt;quote&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;Text Color&lt;/code&gt; to white.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;Text&lt;/code&gt; to something generic such as “This is a placeholder for a favorite quote”.&lt;/li&gt;
&lt;li&gt; Click the Bottom and Right pinning icons to enable pinning to those edges.&lt;/li&gt;
&lt;li&gt;Set the Top edge &lt;code&gt;px&lt;/code&gt; value to 50.&lt;/li&gt;
&lt;li&gt;Set the Left and Right &lt;code&gt;px&lt;/code&gt; values to 200.&lt;/li&gt;
&lt;li&gt;Set the Bottom edge &lt;code&gt;px&lt;/code&gt; value to 0 and the &lt;code&gt;%&lt;/code&gt; to 50.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Location panel properties should look like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8v7cA3oC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/quote-pin-settings.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8v7cA3oC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/quote-pin-settings.png" alt="Pin settings for the quote Text element" width="708" height="1088"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’re pinning the Text element to 200px from the left edge, 200px from the right edge, and 50px from the top edge.&lt;/p&gt;

&lt;p&gt;On the bottom edge we’re pinning to 50% - which is 50% of the height of the template.&lt;/p&gt;

&lt;p&gt;Ensure the &lt;code&gt;Horizontal Alignment&lt;/code&gt; and the &lt;code&gt;Vertical Alignment&lt;/code&gt; are set to &lt;code&gt;Center&lt;/code&gt; and &lt;code&gt;Middle&lt;/code&gt; respectively. This will keep the text in the center on the bounding box in both directions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pDDYhCCd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/quote-in-place.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pDDYhCCd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/quote-in-place.png" alt="The quote element in position" width="880" height="182"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Adding the latest follower images
&lt;/h4&gt;

&lt;p&gt;The next step is to add a series of five Image elements that will show the profile pictures of our five latest followers. &lt;/p&gt;

&lt;p&gt;This data comes from Twitter automatically, so we just need to add the elements and make sure they’re named properly.&lt;/p&gt;

&lt;p&gt;Follow these steps to make a profile image:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click Add an Image, or press &lt;code&gt;I&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Close the Library popup that appears - we don’t need an image at this point.&lt;/li&gt;
&lt;li&gt;Change the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; to 100.&lt;/li&gt;
&lt;li&gt;SHIFT+Click the Bottom Pinning icon. This enables pinning to the bottom edge but also keeps the height you entered - 100 pixels.&lt;/li&gt;
&lt;li&gt;SHIFT+Click the Right Pinning Icon. Likewise, this enables pinning to the right edge but keeps the width you entered at 100 pixels.&lt;/li&gt;
&lt;li&gt;To add a little offset from the very edge, set the Right Pinning &lt;code&gt;px&lt;/code&gt; value to 20. Before leaving this field, press SHIFT+Enter. This sets all &lt;code&gt;px&lt;/code&gt; offsets to 20.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---NeAKiM0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/follower-image-pin-settings.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---NeAKiM0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/follower-image-pin-settings.png" alt="The follower image pin settings" width="720" height="1092"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To finish off the image:&lt;/p&gt;

&lt;p&gt;Set the &lt;code&gt;Stroke Color&lt;/code&gt; to white, and set the &lt;code&gt;Stroke Width&lt;/code&gt; to around 20%. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ap41NZ1F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/stroke-color-width.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ap41NZ1F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/stroke-color-width.png" alt="Setting the stroke color and width" width="708" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, change the &lt;code&gt;API Name&lt;/code&gt; to &lt;code&gt;follower5-image&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your first follower image should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T7WuSFSL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/follower-image-in-place.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T7WuSFSL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/follower-image-in-place.png" alt="The first follower image in place" width="518" height="534"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Making the other four follower images
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;follower5-image&lt;/code&gt; selected, press CTRL+SHIFT+V to duplicate it.&lt;/p&gt;

&lt;p&gt;Change the Right pinning setting as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drop the edge selector down, and instead of edge, choose &lt;code&gt;follower5-image&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Drop the side selector down and choose &lt;code&gt;Left&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make sure the &lt;code&gt;px&lt;/code&gt; value is still 20px.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set the &lt;code&gt;API Name&lt;/code&gt; to &lt;code&gt;follower4-image&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This pins the right hand side of  &lt;code&gt;follower4-image&lt;/code&gt; to the left hand side of &lt;code&gt;follower5-image&lt;/code&gt;  with an offset of 20px.&lt;/p&gt;

&lt;p&gt;Repeat this process 3 more times, duplicating the element and setting the edge selector to the element you previously created.&lt;/p&gt;

&lt;p&gt;Don’t forget to set the &lt;code&gt;API Name&lt;/code&gt; of each new element &lt;code&gt;follower3-image&lt;/code&gt;, &lt;code&gt;follower2-image&lt;/code&gt;, and &lt;code&gt;follower1-image&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NBfuHzrk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/follower-images-in-place.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NBfuHzrk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/follower-images-in-place.png" alt="All the follower images in place" width="880" height="295"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Adding a thank-you note
&lt;/h4&gt;

&lt;p&gt;The last element to add to the template is a thank-you note, thanking your last five followers.&lt;/p&gt;

&lt;p&gt;Follow these steps to add and position this Text element:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;code&gt;Add Text&lt;/code&gt; or press &lt;code&gt;T&lt;/code&gt; to add a Text element.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;Text&lt;/code&gt; to something like “Thank you to my latest followers:”&lt;/li&gt;
&lt;li&gt;Set the Left pinning edge selector down and choose &lt;code&gt;follower1-image&lt;/code&gt; and set the side selector to &lt;code&gt;Left&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click the Right pinning icon to enable it.&lt;/li&gt;
&lt;li&gt;Set the Right pinning edge selector to &lt;code&gt;follower5-image&lt;/code&gt; and set the side selector to &lt;code&gt;Right&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;Height&lt;/code&gt; to 60px.&lt;/li&gt;
&lt;li&gt;SHIFT+Click the Bottom pinning icon to enable it, preserving the 60px height.&lt;/li&gt;
&lt;li&gt;Set the Bottom pinning edge selector to &lt;code&gt;follower1-image&lt;/code&gt; and set the side selector to &lt;code&gt;Top&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the Bottom pinning &lt;code&gt;px&lt;/code&gt; value to 10.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These settings pin the position of your thank-you Text element to the follower images, specifically, to the left edge of &lt;code&gt;follower1-image&lt;/code&gt;, to the right edge of &lt;code&gt;follower5-image&lt;/code&gt;, and 10px above &lt;code&gt;follower1-image&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IjNkNjg5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/thank-you-pin-settings.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IjNkNjg5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/thank-you-pin-settings.png" alt="The thank-you Text element pin settings" width="880" height="1472"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Previewing the template in other sizes
&lt;/h4&gt;

&lt;p&gt;Even though we’re making a Twitter header/cover which are always 1500x500, we can use the Preview control to make sure our template is responsive.&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;P&lt;/code&gt; to open the Previewer and choose some of the other sizes. The follower images and the thank-you message should always be in the bottom-right corner, and the quote should be centered at the top of the template.&lt;/p&gt;

&lt;p&gt;Make sure we’re designing back at &lt;code&gt;1500x500&lt;/code&gt; before closing the Previewer panel.&lt;/p&gt;

&lt;p&gt;Make sure your template is saved and that the &lt;code&gt;API Name&lt;/code&gt; for it is &lt;code&gt;twitter-header&lt;/code&gt;. &lt;/p&gt;
&lt;h3&gt;
  
  
  Connecting to Twitter
&lt;/h3&gt;

&lt;p&gt;Now that the template is created, visit your Profile page to connect Switchboard Canvas to your Twitter account.&lt;/p&gt;

&lt;p&gt;Click the &lt;code&gt;connect to twitter&lt;/code&gt; hyperlink. Twitter’s authorization page will load and ask you to accept the request. Once authorized, Canvas will indicate a successful connection.&lt;/p&gt;
&lt;h3&gt;
  
  
  Using the API
&lt;/h3&gt;

&lt;p&gt;Now we can use the API to create an image from the template. &lt;/p&gt;

&lt;p&gt;You can specify a quote to appear in the Text element in your template.&lt;/p&gt;

&lt;p&gt;Using a REST client such as Insomnia or Postman, make sure your API key is added as the &lt;code&gt;X-API-Key&lt;/code&gt; header, and send a &lt;code&gt;POST&lt;/code&gt; request like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twitter-header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sizes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;elements&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Those who dare to fail miserably can achieve greatly.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will return a response with a link to your new image:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2327&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"warnings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sizes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"warnings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://files.canvas.switchboard.ai/544d9fbe-270a-476c-8612-1b3385e9900c/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="/static/assets/images/twitter-header/pre-update-preview.jpg" class="article-body-image-wrapper"&gt;&lt;img src="/static/assets/images/twitter-header/pre-update-preview.jpg" alt="Pre-update preview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the quote has been set but the follower images have not.&lt;/p&gt;

&lt;p&gt;Send the request again but this time, set the &lt;code&gt;updateTwitterHeader&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"twitter-header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sizes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"elements"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"quote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Those who dare to fail miserably can achieve greatly."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"updateTwitterHeader"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V4XElv2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/post-update-preview.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V4XElv2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/post-update-preview.jpg" alt="Post update preview" width="880" height="293"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--amhIvOv2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.switchboard.ai/static/assets/images/twitter-header/twitter-profile-preview.png" alt="The final Twitter profile preview" width="880" height="543"&gt;
&lt;/h2&gt;

&lt;p&gt;Thanks again to the authors of the following posts for the inspiration!&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/dailydevtips1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0-ei4oTN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--edQh_ULI--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/370165/083a25f4-e79b-42c4-9e5f-0332b834ca5e.png" alt="dailydevtips1"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/dailydevtips1/how-i-made-my-twitter-header-dynamic-68d" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How I made my Twitter header dynamic&lt;/h2&gt;
      &lt;h3&gt;Chris Bongers ・ Jul 5 ・ 6 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#twitter&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;




&lt;div class="ltag__link"&gt;
  &lt;a href="/haideralipunjabi" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C_Zcbn3Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--W5Txj0UC--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/185385/608faca3-e4e7-4d84-afce-2bb485a83dc3.png" alt="haideralipunjabi"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/haideralipunjabi/dynamic-twitter-header-using-python-4hkm" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Dynamic Twitter Header using Python&lt;/h2&gt;
      &lt;h3&gt;Haider Ali Punjabi ・ Sep 10 ・ 6 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#python&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#twitter&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#automation&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  &lt;div class="ltag__link"&gt;
  &lt;a href="/erikaheidi" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i6eXk8o4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--95Vsc3-S--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/162988/b604f249-a248-4582-80e3-4a781d054e3f.jpeg" alt="erikaheidi"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/erikaheidi/how-to-dynamically-update-twitter-cover-image-to-show-latest-followers-using-php-gd-and-twitteroauth-62n" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to Dynamically Update Twitter Cover Image to Show Latest Followers Using PHP GD and TwitterOAuth&lt;/h2&gt;
      &lt;h3&gt;Erika Heidi ・ Jun 2 ・ 11 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;/h2&gt;

&lt;p&gt;Please visit &lt;a href="https://www.switchboard.ai"&gt;https://www.switchboard.ai&lt;/a&gt; if you're interested in automating image generation with an API.&lt;/p&gt;

</description>
      <category>twitter</category>
      <category>header</category>
      <category>switchboardcanvas</category>
      <category>api</category>
    </item>
    <item>
      <title>JavaScript's Import/Export Business</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Mon, 25 May 2020 17:02:43 +0000</pubDate>
      <link>https://dev.to/_adam_barker/javascript-s-import-export-business-2c4d</link>
      <guid>https://dev.to/_adam_barker/javascript-s-import-export-business-2c4d</guid>
      <description>&lt;p&gt;JavaScript really stepped into the import and export business with ES Modules.&lt;/p&gt;

&lt;p&gt;With ES6, the language introduced the &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;export&lt;/code&gt; keywords allowing easier modularization and organization of code.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;import&lt;/code&gt; keyword supports a number of different syntaxes and is often confusing when first thinking about modules.&lt;/p&gt;

&lt;p&gt;Hopefully this article can be a concise explanation of each, and to that end we’ll start with a basic module that exports some things we can use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Marley&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;numberOfLegs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;numberOfLegs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;numberOfLegs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numberOfLegs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;favoriteAnimal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;favoriteAnimal&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have a module that exports three items: a string, a class and a function.&lt;/p&gt;

&lt;p&gt;Notably, the name is just a string but it’s the module’s default export.&lt;/p&gt;

&lt;p&gt;Let’s look at the different ways we can import and use the members from this module.&lt;/p&gt;




&lt;h2&gt;
  
  
  Importing the default export
&lt;/h2&gt;

&lt;p&gt;We can import as much or as little as we need to use from our module. The simplest import brings in the default export: name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// name === "Marley"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;‘Name’ is obviously very broad so we can actually rename this import for use in our module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dogsName&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, ‘name’, the default export, has been imported with an alias. We can refer to this variable in our importing module using ‘dogsName’;&lt;/p&gt;




&lt;h2&gt;
  
  
  Import everything and give it a name
&lt;/h2&gt;

&lt;p&gt;We can import everything from our module and we can give everything that comes in a name that we can use to access what was imported.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;animalStuff&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// animalStuff.name === "Marley";&lt;/span&gt;
&lt;span class="c1"&gt;// animalStuff.favoriteAnimal() = &lt;/span&gt;
&lt;span class="c1"&gt;//    Animal { name: "Dog", numberOfLegs: 4 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Importing one or more exports by name
&lt;/h2&gt;

&lt;p&gt;In addition to importing the default export or everything, we can specify the names of the exports we’d like explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;favoriteAnimal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the first time we’ve seen the curly brackets. These denote that we’re asking for specific members.&lt;/p&gt;




&lt;h2&gt;
  
  
  Importing specific exports and giving them an alias
&lt;/h2&gt;

&lt;p&gt;In this example we can import named exports but alias them so we can use a different name in our importing module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;favoriteAnimal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Importing a module to run side-effects
&lt;/h2&gt;

&lt;p&gt;This is a strange use case in that nothing is actually imported. However, any global code you might have in your module is executed.&lt;/p&gt;

&lt;p&gt;Suppose for example, you had an additional file that contained the following code in &lt;code&gt;extend.js&lt;/code&gt;, responsible for adding a run method to our &lt;code&gt;Animal&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is running!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing is actually exported here, but if we wanted to use the run method in our importing module, we’d need the side-effects import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./extend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Marley&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  import is a Promise: Dynamic Imports
&lt;/h2&gt;

&lt;p&gt;Using import as a function returns a promise; these use cases are known as Dynamic Imports.&lt;/p&gt;

&lt;p&gt;It allows you to conditionally import a module at run-time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weNeedToRun&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./extend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Hopefully this brief primer into the &lt;code&gt;import&lt;/code&gt; syntax has been useful. Check out the official Mozilla docs for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import"&gt;import&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export"&gt;export&lt;/a&gt; for more examples.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>import</category>
      <category>export</category>
      <category>modules</category>
    </item>
    <item>
      <title>Custom Validators for Angular Reactive Forms</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Sun, 24 May 2020 00:22:36 +0000</pubDate>
      <link>https://dev.to/_adam_barker/custom-validators-for-angular-reactive-forms-423f</link>
      <guid>https://dev.to/_adam_barker/custom-validators-for-angular-reactive-forms-423f</guid>
      <description>&lt;p&gt;Angular… ugh, I know.&lt;/p&gt;

&lt;p&gt;But Reactive Forms are actually pretty cool and once you get the hang of them, you can appreciate all of the form dynamics that Angular handles for you.&lt;/p&gt;

&lt;p&gt;At the end of the day we want to supply an object to a form, allow the user to make changes and keep those changes valid.&lt;/p&gt;

&lt;p&gt;Angular provides classes to marry object properties to markup and a convenient &lt;a href="https://angular.io/api/forms/FormBuilder"&gt;&lt;code&gt;FormBuilder&lt;/code&gt;&lt;/a&gt; to help construct groups of form components with default values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Adam&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;21&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Out of the box Angular &lt;a href="https://angular.io/api/forms/Validators"&gt;provides&lt;/a&gt; a set of validators that cover many if not most requirements.&lt;/p&gt;

&lt;p&gt;My name should be longer than 20 characters and clearly I’m no older than 25 so I can specify validators to the FormBuilder object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Adam&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;21&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can check for validation errors in our &lt;code&gt;FormGroup&lt;/code&gt; object with the errors property of each control. This property maintains an object that, when the value is valid, is empty. Otherwise, the object contains keys indicating how the value has failed validation.&lt;/p&gt;

&lt;p&gt;For example, if our name value was say 28 characters, longer than the valid 20 characters,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;formGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;maxLength:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;actualLength:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;requiredLength:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we need something a little extra, something outside the typical &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;required&lt;/code&gt; or &lt;code&gt;email&lt;/code&gt;, we can write a custom validator.&lt;/p&gt;

&lt;p&gt;Suppose we wanted to validate a favorite movie field. Let’s add a movie validator and determined that any value other than Back To The Future is invalid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbstractControl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Back To The Future&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;suppliedMovie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Questionable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we check the control’s value and it’s not the value we want we can return an object specify how the value is invalid. If the value is valid, we return undefined because we don’t want the errors object to be populated in this case.&lt;/p&gt;

&lt;p&gt;It’s a simple change to add our new validator to the FormBuilder call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Adam&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;21&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)]],&lt;/span&gt;

  &lt;span class="c1"&gt;// Instead of using the Validators class we can &lt;/span&gt;
  &lt;span class="c1"&gt;// supply our own validator, movie:&lt;/span&gt;
  &lt;span class="na"&gt;favoriteMovie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Silent Running&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What if we wanted to be less stringent and maybe offer the user of our validation function the option to specify a number of movies that could be favorites.&lt;/p&gt;

&lt;p&gt;Now we need an argument to &lt;code&gt;movie&lt;/code&gt;, like &lt;code&gt;max&lt;/code&gt; and &lt;code&gt;maxLength&lt;/code&gt; do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;validMovies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ValidatorFn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbstractControl&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validMovies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;suppliedMovie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not one of my favorites!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of the &lt;code&gt;movie&lt;/code&gt; function now immediately validating the value and returning an error object, it’s basically a higher-order function and returning a function that Reactive Forms will use. We provide an array of movie names as an argument, and these are used by the function at validation time to check the control’s value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Adam&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;21&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)]],&lt;/span&gt;

  &lt;span class="na"&gt;favoriteMovie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Silent Running&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Teen Wolf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Saving Private Ryan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Inception&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;])]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, Silent Running (excellent movie, &lt;a href="https://www.imdb.com/title/tt0067756/"&gt;criminally downvoted&lt;/a&gt;) is still invalid, but we’ve supplied a list of movies for which the value will be valid.&lt;/p&gt;

&lt;p&gt;Check out the StackBlitz for this example!&lt;br&gt;
&lt;iframe src="https://stackblitz.com/edit/angular-ivy-vpvfxr?embed=1&amp;amp;&amp;amp;" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>angular</category>
      <category>validation</category>
      <category>forms</category>
      <category>factory</category>
    </item>
    <item>
      <title>WWDC2019: Of Course We Need To Work Overtime</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Wed, 05 Jun 2019 15:49:40 +0000</pubDate>
      <link>https://dev.to/_adam_barker/notes-from-wwdc-should-we-put-overtime-to-bed-15e1</link>
      <guid>https://dev.to/_adam_barker/notes-from-wwdc-should-we-put-overtime-to-bed-15e1</guid>
      <description>&lt;p&gt;There's been a big response to a comment Tim Cook said at the recent WWDC2019 event.&lt;/p&gt;

&lt;p&gt;He applauded the engineers and other staff who gave up "nights, weekends, and time from their families".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xZpxPxs4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yu2t423xvgec7wv9wv6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xZpxPxs4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yu2t423xvgec7wv9wv6x.png" alt="courtesy of https://twitter.com/morgan_e_"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was a polarizing comment for sure. The response was full of mixed opinions about the way staff are treated and the way they're made to feel obligated to put in extra time.&lt;/p&gt;

&lt;p&gt;In Apple's case, there were undoubtedly a whole host of complex reasons that led to people overworking to prepare for this event. Aside from the logistics of staging the event and inviting industry professionals and press, there's the significant pressure of being a company under such scrutiny (read as &lt;em&gt;Wall Street&lt;/em&gt;) - that pressure would have been felt exponentially the closer they got to the deadline. &lt;/p&gt;

&lt;p&gt;In other industries the pressure comes from clients. In some fields of law, as in the consulting game, the client is largely dictating the timeframe, and you end up with teams of people working days on end without breaks to meet a deadline.&lt;/p&gt;

&lt;p&gt;Common sense would dictate that clients should understand that if your consulting team is working working around the clock and not sleeping, they're not going to produce the best work for you. However, the market does not run on common sense. The client also knows a price was negotiated, and if the team does not have enough staff to manage the project without overtime, then hire more staff. It's your problem, not mine.&lt;/p&gt;

&lt;p&gt;I actually think the software development industry has done pretty well managing this problem because we enjoy a variety of methodologies that help us track and manage time throughout any given project. &lt;/p&gt;

&lt;p&gt;With Agile, we can break a project down into sprints and estimate work fairly accurately. Agile has not only done a lot for making software development visible to the wider audience, but also for helping us avoid the so-called death-march: working all hours to meet some arbitrary deadline and screwing up our routine in the process. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I think building overtime into your culture is fundamentally wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think someone choosing to put in an extra hour or two to ensure a solid start to the following day or to build in some extra insurance for a future event is fine. As a developer, if I'm working on something and time's getting on, I'll secretly negotiate with myself to get to a certain point because I'll be so much happier tomorrow starting from a cleaner point. In a way that extra effort is locking in my motivation for a later time.&lt;/p&gt;

&lt;p&gt;I'm also a fan of overtime being rewarded on a case by case basis. In contrast, you might be paid a premium knowing your consulting job means you'll be at the mercy of a new deadline all the time. You'll always be working overtime.&lt;/p&gt;

&lt;p&gt;I much prefer the &lt;em&gt;on-demand&lt;/em&gt; model - there might be an important demo and we might need to rally, but after that crunch period the team need to feel that effort is valued on an individual level. They should promptly be rewarded with time off (some multiple of the extra hours they committed) or extra pay (some multiple of their hourly rate).&lt;/p&gt;

&lt;p&gt;Overtime is a common occurrence and often unavoidable but it's the relationship between employer and employee that is most important. No employer should take employees for granted and expect overtime as a given. Everyone has different priorities in their lives and you need to give extra when you expect to receive extra.&lt;/p&gt;




&lt;p&gt;Let me know your thoughts! I'd love to hear about your experiences - whether you feel like you're taken advantage of or whether you feel suitably compensated when crunch time hits. &lt;/p&gt;

</description>
      <category>wwdc2019</category>
      <category>overtime</category>
      <category>timcook</category>
      <category>apple</category>
    </item>
    <item>
      <title>Python &amp; Pandas Course</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Thu, 30 May 2019 15:41:27 +0000</pubDate>
      <link>https://dev.to/_adam_barker/python-pandas-course-9ka</link>
      <guid>https://dev.to/_adam_barker/python-pandas-course-9ka</guid>
      <description>&lt;p&gt;Not incentivized in any way but I just happened to stumble across a code for Udemy's &lt;a href="https://www.udemy.com/course/data-analysis-with-pandas/"&gt;Python &amp;amp; Pandas course&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Get it free with code: APRILMAGIC.&lt;/p&gt;

&lt;p&gt;I guess the magic is the code still works when it's basically June. 🤷🏻‍♂️&lt;/p&gt;

</description>
      <category>udemy</category>
      <category>python</category>
      <category>pandas</category>
      <category>datascience</category>
    </item>
    <item>
      <title>One Way to Level Up Your Development Career</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Sun, 26 May 2019 16:05:23 +0000</pubDate>
      <link>https://dev.to/_adam_barker/one-way-to-level-up-your-development-career-4kcn</link>
      <guid>https://dev.to/_adam_barker/one-way-to-level-up-your-development-career-4kcn</guid>
      <description>&lt;p&gt;&lt;strong&gt;Over the past few years&lt;/strong&gt; I’ve been asked a few times what’s the best way to ‘level up’ a development career.&lt;/p&gt;

&lt;p&gt;As developers we primarily think in terms of the languages and frameworks we need to learn, how to go about utilizing best practice and being good, compassionate team players.&lt;/p&gt;

&lt;p&gt;I think one of the best ways to level up is to spend time thinking about how what you and your team works on benefits the company or client you’re working for. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sounds obvious right?&lt;/strong&gt; Your product manager, architect or team lead outlines what needs to be done and as a team or freelance developer you build and deploy that thing.&lt;/p&gt;

&lt;p&gt;But where you can differentiate is reverse engineering the company’s vision and applying your technical skills to directly affect that vision. &lt;/p&gt;

&lt;p&gt;A non-technical CEO or manager will far more appreciate your value if you’re empathetic to the bigger picture than just operating in siloed sprints, features or bug-fixes that we’re used to in the day to day.&lt;/p&gt;

&lt;p&gt;Demonstrating that you’re capable of thinking at those two distinct levels is a huge advantage. One of the most effective ways to do this is to think in terms of the &lt;strong&gt;cost&lt;/strong&gt; of a specific decision. Sure, your manager or tech lead may have already decided on the best solution for a given problem but if you can display empathy for the same decision making process, they’ll see you as someone invested in helping them solve the same problems, someone operating on the same level, and someone who helps them do their job as well as your own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Having co-founded a startup&lt;/strong&gt;, I love it when our team suggests different ways of solving a problem taking cost into account. It may be the use of a different AWS service that benefits us over the long term, an admin function that gives extra visibility into a sensitive area, or use of a new framework that will save the team a ton of time.&lt;/p&gt;

&lt;p&gt;In essence, they’re thinking holistically about how they can benefit the wider business before diving into technical details. &lt;/p&gt;

&lt;p&gt;In small companies and startups it’s a lot easier to do this because you’re so much closer to founding or ‘senior’ people, but if you’re in a larger company, demonstrating empathy to your manager is a great quality that will travel well in positive word of mouth.&lt;/p&gt;

&lt;p&gt;Crucially it creates a lot of trust that you have the business’s best interests at heart. This often gets rewarded when businesses need to pivot or create new functions that need new leaders. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be the first name that springs to your manager's mind when this happens!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>business</category>
      <category>perception</category>
      <category>empathy</category>
    </item>
    <item>
      <title>Is it dev dot too or is it dev dot tee oh?</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Sat, 11 May 2019 00:39:30 +0000</pubDate>
      <link>https://dev.to/_adam_barker/is-it-dev-dot-too-or-is-it-dev-dot-tee-oh-54do</link>
      <guid>https://dev.to/_adam_barker/is-it-dev-dot-too-or-is-it-dev-dot-tee-oh-54do</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4xc4b8ei79l6m7w0hnp3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4xc4b8ei79l6m7w0hnp3.jpg" alt="Man, freaking out. circa 2019"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So literally my whole entire life I've been pronouncing this site as "dev dot too" but I've just heard someone refer to it as "dev dot tee oh".&lt;/p&gt;

&lt;p&gt;Now I'm freaking out. I'm freaking out mostly with &lt;em&gt;relief&lt;/em&gt; as I realized I've not actually verbalized the site's name in front of anyone and have therefore spared myself what I can only imagine to be considerable embarrassment.&lt;/p&gt;

&lt;p&gt;But it made me think: the last time I did this was many years ago when people couldn't decide if GIFs had a hard or soft &lt;strong&gt;G&lt;/strong&gt;. Is hard or soft &lt;strong&gt;G&lt;/strong&gt; like tabs vs spaces?&lt;/p&gt;

&lt;p&gt;So now I want to hear examples of when people called things the wrong thing for the longest time...&lt;/p&gt;

&lt;p&gt;...or had that moment when they heard someone pronounce something and thought &lt;em&gt;I never thought I should say it like that.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Comment and let me know! 👇👇👇👇&lt;/p&gt;

</description>
      <category>devto</category>
      <category>funny</category>
      <category>fauxpas</category>
    </item>
    <item>
      <title>The Day Everyone Turned Into Michael Johnson. A Lesson In F5.</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Sun, 15 Apr 2018 18:27:50 +0000</pubDate>
      <link>https://dev.to/_adam_barker/the-day-everyone-turned-into-michael-johnson-a-lesson-in-f5-7dj</link>
      <guid>https://dev.to/_adam_barker/the-day-everyone-turned-into-michael-johnson-a-lesson-in-f5-7dj</guid>
      <description>&lt;p&gt;There is no real point to this article - it’s not one of my usually strong lectures and doesn’t feature a key take-away or call to action.&lt;/p&gt;

&lt;p&gt;It’s just something hilarious that happened many years ago that I recently remembered.&lt;/p&gt;

&lt;p&gt;I think it was 2002 and I’d joined a small company in the UK as a software developer. (This was before new companies were called startups and before joining new companies was cool). The company had designed a telecoms product and offered businesses unlimited calls for a low(ish) monthly cost.&lt;/p&gt;

&lt;p&gt;At the time it was a revolutionary idea and we gained many customers quickly. We’d developed the billing system, we ran business development, we had a tiny call centre, everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classic ASP
&lt;/h3&gt;

&lt;p&gt;Our tech stack was largely Microsoft based. We had a classic ASP website and we ran on SQL Server. Everything kinda ran well, but what we lacked was any sort of contigency. We’d grown so quickly that no-one had had the time to think about disaster recovery or database backups or even source control.&lt;/p&gt;

&lt;p&gt;Unit and integration testing didn’t exist, exception handling was minimal and problems were fixed as we found them - in production.&lt;/p&gt;

&lt;p&gt;You can see where this is going.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Billing Run
&lt;/h3&gt;

&lt;p&gt;The single most important monthly event for us was the Billing Run. This essentially consisted of running a job that would calculate every customer’s bill and generate a document that would by electronically sent to an off-site printing location. From there the bills would be packaged into branded stationery and mailed to the customers. Once a bill was generated, it would be saved into a online location so that we had a PDF copy of what was created for reference.&lt;/p&gt;

&lt;p&gt;The Billing Run was always a stressful time. Because we were largely hands-off after the job hard started running, we would always worry that bills would be accurate and that we were correctly calculating everything. (Deep down we knew something would always go wrong because we’d rushed everything).&lt;/p&gt;

&lt;h3&gt;
  
  
  Bob
&lt;/h3&gt;

&lt;p&gt;My co-worker at the time was a wonderful chap. After we met we became close friends and for this reason he won’t mind me saying that despite being a software developer, software development was not his strong suit. I’ll do him the honor of protecting his identity and call him Bob. (His name was actually Bob).&lt;/p&gt;

&lt;p&gt;Bob had the remarkable ability to… let’s say, break things. I’m not sure he actually meant to wreak such havoc but he had a wonderful track record of deleting things, losing things, dropping databases and tables, being late for work, forgetting to go home from work, forgetting where the office was. The list is quite endless.&lt;/p&gt;

&lt;h3&gt;
  
  
  UPDATE dbo.customers...
&lt;/h3&gt;

&lt;p&gt;One day we had a request come down from the call center. A customer’s name had a typo and it needed fixing. The customer was upset. The operator in the call center couldn’t change the name because of a bug in the system. Naturally.&lt;/p&gt;

&lt;p&gt;We were all fairly nervous because we were right in the middle of the Billing Run. Generally changing anything mid Billing Run as considered a bad idea. We were even scared to answer the phone during the Billing Run.&lt;/p&gt;

&lt;p&gt;Anyway Bob took the call and heard the story about how Michael Jonson was missing an ‘H’, and was subsequenly excited to realize he could probably fix this with the minimum impact. A simple database update. It wasn’t like he had to make a code change and redeploy something, after all.&lt;/p&gt;

&lt;p&gt;Anyone familiar with the majority of SQL tools these days knows that while you can be authoring large scripts or procedures, it’s also possible to highlight a portion of script and execute it in isolation.&lt;/p&gt;

&lt;p&gt;Such functionality was Bob’s downfall that day, for Bob authored a statement such as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
UPDATE dbo.customers SET firstName=‘Michael’, lastName=‘Johnson’&lt;br&gt;
WHERE id = 187222;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(Savvy administators will be wondering why our tables were in the dbo schema. My response is: Good point.&lt;/p&gt;

&lt;p&gt;Secondly I need to point out that 187222 is an arbitrary number and does not, in the slightest, indicate the number of customers we had).&lt;/p&gt;

&lt;p&gt;Bob then proceeded to take his mouse and highlight the statement and press F5, immediately executing the statement. Only he didn’t highlight both lines, just the first.&lt;/p&gt;

&lt;p&gt;At this point, everyone in our production customer table had the same name.&lt;/p&gt;

&lt;p&gt;These days my responses to mistakes are more professional, but at the time I burst out laughing. It was so… Bob.&lt;/p&gt;

&lt;p&gt;A few short minutes later we got a call from the off-site printing location informing us that everyone’s bill suddenly had the same name. We’d need to rerun the Billing Run.&lt;/p&gt;

&lt;p&gt;Obviously we didn’t have a very recent backup of the production database and Bob spent the next few hours tracking it down, restoring it, and correcting all the customer’s names. &lt;/p&gt;

&lt;p&gt;By the time we could rerun the Billing Run, the billing period was slightly off which meant we’d need to include a letter in everyone’s billing telling them what had happened. &lt;/p&gt;

&lt;p&gt;There are many lessons to be learned here. Bob didn’t get to learn any of them, he was fired immediately. That’s a joke of course, you can’t fire anyone in the UK. But things have moved on and thankfully development methodologies and general DevOps have many safeguards in place. &lt;/p&gt;

&lt;p&gt;Still, I’ll always think of Michael Johnson when I press F5.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>humor</category>
      <category>microsoft</category>
      <category>bob</category>
    </item>
    <item>
      <title>One of the Most Useful Software Development Skills Has Nothing To Do With Software Development</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Tue, 10 Apr 2018 20:27:41 +0000</pubDate>
      <link>https://dev.to/_adam_barker/one-of-the-most-useful-software-development-skills-has-nothing-to-do-with-software-development-22l6</link>
      <guid>https://dev.to/_adam_barker/one-of-the-most-useful-software-development-skills-has-nothing-to-do-with-software-development-22l6</guid>
      <description>&lt;p&gt;One of the reasons software developers love what they do is because they love learning.&lt;/p&gt;

&lt;p&gt;When you first start to learn a programming language, it can feel like an overwhelming undertaking.&lt;/p&gt;

&lt;p&gt;Especially these days.&lt;/p&gt;

&lt;p&gt;When I was 14 I took a three week work experience job at a small software development house and I remember the owner being marginally impressed at a game I’d written (in AMOS for the Commodore Amiga - yep, that long ago), but then he looked at me and said:&lt;/p&gt;

&lt;p&gt;“You need to learn C.” &lt;/p&gt;

&lt;p&gt;With one language I could have recreated all the products that software house had developed. But these days, you need knowledge of multiple languages and multiple frameworks, knowledge of databases, knowledge of DevOps-style tasks so you can deploy your creations, knowledge of compilers, transpilers, build tools and containers.&lt;/p&gt;

&lt;p&gt;Despite the enormous array of tools available with which to build applications, these skills are a commodity. It’s true that the longer you spend learning the more confident you become that you can learn something else. But there are other skills that are as important, if not more important in today’s environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mindset: Don’t write code, solve problems.
&lt;/h2&gt;

&lt;p&gt;I once worked for a software company that employed maybe around 50 developers, but two stood out. &lt;/p&gt;

&lt;p&gt;These two were the true rock stars. Their opinions were valued above all others and it often seemed like they ran the company themselves. They enjoyed direct access to the top of the tree and their every wish granted by the executive team.&lt;/p&gt;

&lt;p&gt;I wondered what it was about them that garnered such respect by the company’s founders. I felt I’d had the same amount of experience and offered the same skill level.&lt;/p&gt;

&lt;p&gt;Eventually it occurred to me. &lt;/p&gt;

&lt;p&gt;They didn’t write software, they solved problems. &lt;/p&gt;

&lt;p&gt;I think one of the best skills to deploy if you’re joining a small company is to be empathetic towards the company’s goals. There will be many priorities over creating perfect bug-free software and establishing solid methodologies and 100% test coverage. Unless the company has raised considerable capital and can afford to hire a huge team that takes 3 months to put everything in place, you will just need to be in build mode, and your product needs to be done and out the door in 3 months.&lt;/p&gt;

&lt;p&gt;You won’t always have the luxury of time to make everything perfect or refactor some code to where you’d like it. Sometimes bugs have to stay unfixed or features left out because the business has greater priorities. Showing respect for these, and driving your decisions from these can make a huge difference. &lt;/p&gt;

&lt;p&gt;Experience helps in these cases because experience will help you make better decisions - mostly in terms of what not to waste time doing. Speed is the priority in those early days.&lt;/p&gt;

&lt;p&gt;If you’re able to demonstrate empathy to the company’s founders, it puts you in a great position to build trust and loyalty because they know you’re on their side; that you’re invested in all facets of the business and are not just an employee or a siloed member of the team. &lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>empathy</category>
      <category>solvingproblems</category>
      <category>mindset</category>
    </item>
    <item>
      <title>The Super-Brief History of JavaScript Frameworks For Those Somewhat Interested</title>
      <dc:creator>Adam Barker</dc:creator>
      <pubDate>Mon, 02 Apr 2018 18:22:37 +0000</pubDate>
      <link>https://dev.to/_adam_barker/the-super-brief-history-of-javascript-frameworks-for-those-somewhat-interested-3m82</link>
      <guid>https://dev.to/_adam_barker/the-super-brief-history-of-javascript-frameworks-for-those-somewhat-interested-3m82</guid>
      <description>&lt;p&gt;JavaScript frameworks have come a long way and any new developer is not only faced with learning a language but choosing with framework to learn first.&lt;/p&gt;

&lt;p&gt;The choice available today is a result of some incredible innovation in a relatively short space of time. As recently as 2004, Google released Gmail which is regarded as the first everything-in-the-browser product we know today as Single Page Applications.&lt;/p&gt;

&lt;p&gt;If you're just starting to learn JavaScript, you arrive at a good time, but there wasn't always so much choice and flexibility if you wanted to do anything interesting in the browser.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dynamic HTML
&lt;/h1&gt;

&lt;p&gt;In the early 2000’s, JavaScript was largely in its infancy, and was mostly used to perform basic changes to a page. The highlights included mouse-overs, dropdown menus and scrolling text - things developers take for granted today with the power of CSS.&lt;/p&gt;

&lt;p&gt;Back then, Internet Explorer dominated the web browser landscape (I know, weird right?) and since 1999, included a wrapper around a library Microsoft had developed for their own e-mail product, Outlook. The lovely but dauntingly named XMLHttpRequest object eventually became standardized across browsers and was the gateway to how we experience much of the Web today.&lt;/p&gt;

&lt;p&gt;Crucially, this XMLHttpRequest allowed requests to be sent to a server, and a response processed, without having to refresh the browser or perform a full round trip. Until then, things like clicking a tab or posting a form meant the server processed that request and decided how to render the response, and the browser would spin away and eventually show the result.&lt;/p&gt;

&lt;p&gt;Developers jumped on the functionality and saw the potential to create real desktop-replacement applications on the web. Asynchronous Javascript and XML, shortened to AJAX, was the phrased coined to describe this newfound ability.&lt;/p&gt;

&lt;h1&gt;
  
  
  jQuery
&lt;/h1&gt;

&lt;p&gt;jQuery wasn’t technically the first JavaScript framework, but its popularity exploded after it was released in 2006. jQuery aimed to solve many of the issues developers faced with subtle differences in web browser implementations, and it abstracted much of the functionality developers wanted into a clean and easy to learn framework.&lt;/p&gt;

&lt;p&gt;With the potential to build applications that harnessed the convenience of the web, developers built larger and larger solutions that tested jQuery’s maintainability. Products like Gmail had demonstrated what could be achieved but it became clear more enterprise friendly tooling might be needed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Backbone &amp;amp; AngularJS
&lt;/h1&gt;

&lt;p&gt;In 2010, Jeremy Ashkenas released Backbone, the first framework aimed at creating single page applications. Jeremy had seen how messy a huge jQuery application could become and wanted a cleaner approach to remedy the thousands of selectors and interwoven event handlers. Interestingly, Backbone didn’t require jQuery, it was an independent framework but certain functionality could be enabled if jQuery was present.&lt;/p&gt;

&lt;p&gt;Around the same time, Adam Abrons and Misko Hevery created AngularJS, which soon after fell under Google’s care when Hevery took a job at the company. Angular was the first framework that provided a complete architecture for front-end application development. &lt;/p&gt;

&lt;p&gt;One of AngularJS’s main features was bi-directional data binding and provided a way to bind a model’s data to HTML markup and have changes update in real-time. Developers called this ‘automagic’. Angular also supported dependency injection and the ability to create reusable components.&lt;/p&gt;

&lt;h1&gt;
  
  
  Knockout, Meteor, React
&lt;/h1&gt;

&lt;p&gt;Knockout is another framework that provided a solution to bi-directional data binding, although it provides only a fraction of the functionality of AngularJS. Meteor too, had a significant following but in 2013, Facebook released its React framework and has since enjoyed huge popularity.&lt;/p&gt;

&lt;p&gt;Many new developers first hear about React and make it their framework of choice. Despite this, React does has a relatively steep learning curve, but it also benefits from excellent documentation and an enormous community.&lt;/p&gt;




&lt;p&gt;For a developer it’s very interesting to see the way frameworks have tried to solve the problems of their predecessors. I think Angular (certainly the most recent versions) share a lot with React and in turn they both share common goals with Vue, the new kid on the block.&lt;/p&gt;

&lt;p&gt;Another consideration that has become increasingly important is how easily these frameworks can support mobile targets. Ionic and React Native have proven to be considerable players as teams attempt to standardize on JavaScript as a language for all means: server side with NodeJS, desktop and mobile browser, and targeting native devices with the help of additional frameworks.&lt;/p&gt;




&lt;p&gt;In summary, JavaScript is a great language to learn and with these frameworks, almost anything is possible on any device. With each new release of a framework there is much evidence of learning from previous incarnations so there's never a better time to dive in and start to build your first application.&lt;/p&gt;

</description>
      <category>javascriptframeworks</category>
      <category>angular</category>
      <category>react</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
