Tag: components

  • How to fix an Angular component that won’t stick

    How to fix an Angular component that won’t stick

    If you’re working in a component-driven framework like Angular, you might notice one day that your components start ignoring your router’s scroll events and are no longer sticky. All of a sudden, you find the only way to keep your components from scrolling off the page is by assigning them a fixed position with CSS. The only reason this works is because the closest positioned ancestor your components can find is the last possible resort, Document, which represents the whole DOM.

    What do you mean by ‘sticky’?

    Just to be clear, I’m referring to the CSS property ‘position’ that has the following possible values:

    1. static – no special positioning
    2. relative – normal positioning
    3. fixed – always in the same place, regardless of scroll
    4. absolute – always in the same place relative to its closest ancestor that has positioning
    5. sticky – always in the same place after it reaches a top, right, bottom, or left scroll position

    Using sticky is like fixed + relative.

    Fixed is cool if you only care about positioning in respect to the viewport. But using it means your components no longer take space in the DOM, and therefore no longer have any relation to the positioning of everything else in the DOM. This runs the risks for things like overlapping, cropped and/or empty content.

    What kinds of issues are we talking about?

    1. Applying sticky has no effect on component. It scrolls out of viewport with everything else.
    2. Applying sticky has partial effect on component. It stays in the right spot until you scroll past the entire length of the screen.

    Steps to troubleshoot

    Make sure you’ve specified at least a top, left, right or bottom position on the component you’re trying to make sticky.

    You can used fixed or relative units, but you must specify at least a top, left, right or bottom position or else it won’t know where to stick.

    Make sure your component’s container has a defined height or width.

    Your component needs to know the dimensions of its container in order to calculate where the sticking point is in relation to itself. It will continue checking its ancestors until it finds one with positioning.

    Make sure your component’s container does NOT have overflow set to hidden.

    Once you’ve scrolled your component out of the viewport, it is considered overflow. Therefore, hiding the overflow on a sticky element that needs overflow to stick won’t work.

    But what if the height is dynamic?

    Let’s say you want the footer to always start at the bottom of the page, even if there’s not enough content to push it down. If you set the component’s container height to 100% and it doesn’t stretch to the end of the page, you might try 100vh. While that works and your component might be sticky at first, you may notice it stops sticking after you’ve scrolled past the full length of the page.

    To solve this problem, set the following styles on your component’s container:

    .container {
       ...
       min-height: 100vh;
       height: 100%;
     }
    
  • Why Angular components, pipes, and directives should stand alone and what that means for modules

    Why Angular components, pipes, and directives should stand alone and what that means for modules

    Don’t get me wrong – I really love Angular modules. They are like that office manager who keeps track of everything in their head and runs everything like a nearly infallible machine.

    But if you are developing a UI component library, it gets very tedious to have to create a module just so something can use your one component. Modules are meant for groupings, and they are great at that. But for generic components, they can be overkill.

    What difference does a module make?

    Before standalone, the only way to use a component, directive, or pipe was to declare them in a module that had to be imported by whoever wanted to use them. If you declared multiple items in the same module, it became hard to track what was being imported for what and what was no longer being used. This ran the risk of importing things unnecessarily, causing bloated bundle sizes and subsequently slower app times.

    As of Angular 14, the brilliant Angular team added standalone functionality. In other words, components, directives, and pipes can import what they need directly without modules just like any other import.

    You can import components, directives or pipes directly to use them!

    Lazy load with less files

    Before standalone, the only way to lazy load was to create a module with routing to serve as a locator to get to the correct component without any knowledge of what that component is. Now we can point to the component with imports instead of routes.

    Should I switch everything to standalone?

    I can’t think of a good reason to declare components, directives, and pipes with modules ever again. Please let me know if you can think of reasons why you should.

    What good are modules then?

    Modules are still super useful, just less needed…like a lot less needed. Actually, if you use them just for grouping and are no longer concerned with the dependencies of what you’re declaring, how to best use modules will become a lot clearer.

    For example, if you’re importing the same group of components, directives, and/or pipes across multiple places or want to alter what’s being imported in one spot, you should bundle them in a module. Don’t use the module to declare anything. Only use it for importing/exporting what you need.

    Another example would be if you are using things that rely on each other, like a component that uses a directive to interact with its children. But even then, just use the module to import/export.

    Which Angular decorators can be standalone?

    • Components
    • Directives
    • Pipes

    How do you become standalone?

    By Angular CLI

    ng g c componentName --standalone
    

    By component metadata

    @Component({
      standalone: true,
      selector: 'your-selector',
      imports: [
        CommonModule,
        ExampleModule
      ],
      ...
    })
    

    If you’re using an existing decorator, you need to delete it from the module that’s declaring it. You can be declared by a module or have standalone turned on but not both.

  • The right way to componentize SVGs for your Angular app

    The right way to componentize SVGs for your Angular app

    Last year, I wrote an article about how to create an SVG library in Angular by making components that link to SVG files instead of HTML templates. Shortly afterwards, my boss tasked me with finding a solution to the excessive DOM size problem, which we discovered was being caused by all of the elements that make up our SVGs.

    How to create references instead of actual clones to your SVGs

    After doing extensive research and trying different methods, I came across the ‘symbol’ and ‘use’ HTML elements. This article gives great in-depth explanations into why this is the correct approach.

    If you have ever worked in Flash…I mean Animate, you will remember how awesome symbols were. They enabled you to create one symbol and then reference that symbol so any changes you did to the original were cascaded to all of its references. By using ‘symbol’ and ‘use’, you are essentially doing the same thing.

    To make this solution even more enticing, the ‘use’ element acts as a container and stores its children in the shadow DOM. In other words, your SVG elements no longer count towards your DOM size.

    The drawbacks of the shadow DOM and how to overcome them

    There are some drawbacks though with using a closed shadow DOM. For example, you can’t access or manipulate the SVG’s viewBox through JavaScript. Therefore, you won’t be able to do things like pull out the SVG’s exact dimensions without inspecting the element through a browser or updating the paths of the SVG without an image editor.

    This can be problematic because if you don’t set the SVG’s width and height, it will automatically have a width of 300 pixels and a height of 200 pixels. If your SVG is considerably smaller, you will see a lot of blank space around the SVG. Because we’re going to create one component for all of your SVGs, you can’t set one universal viewBox to handle this problem.

    The viewBox isn’t the only thing that’s inaccessible. All of the SVG’s styles are as well. This is actually a pretty good benefit because a change to the original would be applied to all of its references.

    Don’t fret; we can easily overcome these hurdles by making our SVG generic and adaptable. We can use properties like ‘inherit’ on the SVG’s width and height and ‘currentColor’ for its fill and outline so they can be set through a parent or ancestor.

    How to create the SVG component

    Step 1: Create a graphic and export it as an SVG

    Note: In order to individually style your SVG and have it scale gracefully to any size, you must use actual paths instead of embedded images for your SVGs.

    For example, I made my logo with vector art using Illustrator. This is what it looks like when I export just the cloud as an SVG:

    <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 229 149.04">
      <path d="M189.37,142a12.35,12.35,0,0,1-3.2-3c-1.26-1.65-2.31-3.5-3.71-5a12.12,12.12,0,0,0,2.48,4.77A12.55,12.55,0,0,0,189.37,142Z" transform="translate(0 0)" style="fill:#ccc"/>
      <path d="M192.89,142.94a12.66,12.66,0,0,1-3.52-1A6.19,6.19,0,0,0,192.89,142.94Z" transform="translate(0 0)" style="fill:#ccc"/>
      <path d="M182.46,133.91a11.83,11.83,0,0,1-.4-3.65,5,5,0,0,0-1.2,2.21,1.51,1.51,0,0,1,.26.18A10.64,10.64,0,0,1,182.46,133.91Z" transform="translate(0 0)" style="fill:#ccc"/>
      <path d="M229,76.35a28.33,28.33,0,0,0-19-26.61,14.29,14.29,0,0,0,1.32-6,14.8,14.8,0,0,0-14.93-14.67h-.09a15.07,15.07,0,0,0-10.47,4.2,27.92,27.92,0,0,0,.45-5C186.28,12.67,173.36,0,157.43,0a28.94,28.94,0,0,0-25.81,15.64,24.52,24.52,0,0,0-2.7-.2A29.22,29.22,0,0,0,113.33,11C97.4,11,84.48,23.62,84.48,39.25a28.41,28.41,0,0,0,.15,2.92c-2.79-.57-5.76-1.72-8.51-2.21-4.42-.54-8.85,2.71-12.19,5.47a36.36,36.36,0,0,0-3.47,3.66A31.66,31.66,0,0,0,52.9,67.61c-.56,13,10,21.14,18.8,29.27,1.1,1.63,0,4.88,1.1,5.42,3.32,3.26,6.64-2.71,6.08-6-1.1-4.88-6.08-6-8.84-9.22-3-3.25-2.91-7.58-1-11.31a14.81,14.81,0,0,1,2.49-3.44c3.45-4.22,9-3.68,13.41-2.59,7.19,2.17,14.93,6,16.6,13.59-.06,1.62-.15,3.29-.28,5-1.06,13.49-4.32,26.82-15.67,35.58-8.37,6.46-19.16,9.14-29.75,10.3s-21.32.93-31.87,2.4c14.49-4.51,29.91-5.73,44.28-10.58,7.48-2.53,14.82-6.18,19.89-12.12a35.54,35.54,0,0,0,7.68-17.8c1.05-6.79.27-14.5-4.81-19.23-3.5-3.26-9.84-4.22-12.87-.53s-1.07,9,1.5,12.82A19.63,19.63,0,0,1,78,83.06a6.67,6.67,0,0,1,2.37-5.66c2.14-1.58,5.3-1.22,7.48.29a13.06,13.06,0,0,1,4.46,6.37,28.19,28.19,0,0,1-3,25.38C82.12,120,68.58,124.6,55.72,126.23,46.5,127.4,37.17,127.4,28,128.57S-12.06,144.48,5.1,148c16,3.23,88.05-1.41,106.45-9.34s34.35-20.07,54.15-24.38c5-1.09,9.4,0,13.82,2.71,7.19,4.34,6.08,11.92,6.08,18.43,0,2.17,2.21,4.88,4.43,4.88,7.74,0,13.82-7.59,14.37-14.64-.56,7.19-5.48,20.7-15.52,16.76-2.32-.91-4.12-2.73-5.85-4.5a6.9,6.9,0,0,0,2.39,3.76,13.57,13.57,0,0,1-2.71-2.53,9,9,0,0,1-2-4.36,6,6,0,0,1,.14-2.27,1.53,1.53,0,0,0-.51-.21,1.2,1.2,0,0,0-1.17.87c-1.87,5.72,7.7,10.77,12.16,11.31,9.91,1.22,17.12-7.21,19.47-15.79a43.86,43.86,0,0,0,1.13-5.79,23.09,23.09,0,0,0,0-7.42c-.18-1.22-.43-2.44-.72-3.66a21.87,21.87,0,0,0-1.13-4.29c-.48-1.38-1-2.76-1.39-4.12A28.37,28.37,0,0,0,229,76.35Zm-39.19,67.34a21.89,21.89,0,0,0,5.3.41,13.85,13.85,0,0,1-5.32-.41Z" transform="translate(0 0)" style="fill:#ccc"/>
     </svg>
    

    Step 2: Prepare your SVG

    The next step is to add ‘symbol’ tags to the elements inside of your SVG and to move the viewBox to the newly created ‘symbol’ element. You must also add an id attribute to the symbol so that you can call it externally.

    If you want to change the colors differently for each reference, you have to set the ‘fill’ and ‘outline’ attributes to ‘currentColor’ or ‘inherit’. Use ‘currentColor’ to set the color through the ‘color’ property. Use ‘inherit’ to set the color through the ‘path’ property.

    I also learned a trick from using Font Awesome icons. You can automatically make the SVG be two-colored by setting the opacity of the secondary color.

    Now, your SVG will look something like this:

    <svg xmlns="http://www.w3.org/2000/svg">
      <symbol id="ces-logo-cloud"  viewBox="0 0 228.98 148.98">
        <path opacity="0.4" d="M189.37,142a12.22,12.22,0,0,1-3.2-3c-1.26-1.65-2.31-3.5-3.71-5a12.12,12.12,0,0,0,2.48,4.77A12.6,12.6,0,0,0,189.37,142Z"/><path opacity="0.4" d="M192.89,142.94a12.74,12.74,0,0,1-3.52-1A6.2,6.2,0,0,0,192.89,142.94Z"/><path opacity="0.4" d="M182.46,133.91a11.83,11.83,0,0,1-.4-3.65,5,5,0,0,0-1.2,2.21,2.4,2.4,0,0,1,.26.18A10.68,10.68,0,0,1,182.46,133.91Z"/><path fill="currentColor" d="M229,76.35a28.34,28.34,0,0,0-19-26.61,14.29,14.29,0,0,0,1.32-6A14.8,14.8,0,0,0,196.3,29.07a15.06,15.06,0,0,0-10.47,4.2,28.12,28.12,0,0,0,.45-5C186.28,12.67,173.36,0,157.43,0a28.92,28.92,0,0,0-25.81,15.64,24.52,24.52,0,0,0-2.7-.2A29.18,29.18,0,0,0,113.33,11C97.4,11,84.48,23.62,84.48,39.25a28.26,28.26,0,0,0,.15,2.92c-2.79-.57-5.76-1.72-8.51-2.21-4.42-.54-8.85,2.71-12.19,5.47a37.46,37.46,0,0,0-3.47,3.66A31.68,31.68,0,0,0,52.9,67.61c-.56,13,10,21.14,18.8,29.27,1.1,1.63,0,4.88,1.1,5.42,3.32,3.26,6.64-2.71,6.08-6-1.1-4.88-6.08-6-8.84-9.22-3-3.25-2.91-7.58-1-11.31a14.86,14.86,0,0,1,2.49-3.44c3.45-4.22,9-3.68,13.41-2.59,7.19,2.17,14.93,6,16.6,13.59-.06,1.62-.15,3.29-.28,5-1.06,13.49-4.32,26.82-15.67,35.58-8.37,6.46-19.16,9.14-29.75,10.3s-21.32.93-31.87,2.4c14.49-4.51,29.91-5.73,44.28-10.58,7.48-2.53,14.82-6.18,19.89-12.12a35.52,35.52,0,0,0,7.68-17.8c1.05-6.79.27-14.5-4.81-19.23-3.5-3.26-9.84-4.22-12.87-.53s-1.07,9,1.5,12.82A19.62,19.62,0,0,1,78,83.06a6.66,6.66,0,0,1,2.37-5.66c2.14-1.58,5.3-1.22,7.48.29a13.1,13.1,0,0,1,4.46,6.37,28.18,28.18,0,0,1-3,25.38C82.12,120,68.58,124.6,55.72,126.23,46.5,127.4,37.17,127.4,28,128.57S-12.06,144.48,5.1,148c16,3.23,88.05-1.41,106.45-9.34s34.35-20.07,54.15-24.38c5-1.09,9.4,0,13.82,2.71,7.19,4.34,6.08,11.92,6.08,18.43,0,2.17,2.21,4.88,4.43,4.88,7.74,0,13.82-7.59,14.37-14.64-.56,7.19-5.48,20.7-15.52,16.76-2.32-.91-4.12-2.73-5.85-4.5a6.88,6.88,0,0,0,2.39,3.76,13.55,13.55,0,0,1-2.71-2.53,8.92,8.92,0,0,1-2-4.36,6,6,0,0,1,.14-2.27,1.42,1.42,0,0,0-.51-.21,1.19,1.19,0,0,0-1.17.87c-1.87,5.72,7.7,10.77,12.16,11.31,9.91,1.22,17.12-7.21,19.47-15.79a44.22,44.22,0,0,0,1.13-5.79,23.09,23.09,0,0,0,0-7.42c-.18-1.22-.43-2.44-.72-3.66a21.43,21.43,0,0,0-1.13-4.29c-.48-1.38-1-2.76-1.39-4.12A28.37,28.37,0,0,0,229,76.35Zm-39.19,67.34a21.82,21.82,0,0,0,5.3.41A13.73,13.73,0,0,1,189.79,143.69Z"/>
      </symbol>
    </svg>
    

    Step 3: Create a component that will fetch your SVGs

    svg.component.ts

    import { Component, Input, OnInit } from '@angular/core';
    import { SvgSize } from './svg';
    
    @Component({
      selector: 'ces-svg',
      templateUrl: './svg.component.html',
      styleUrls: ['./svg.component.scss']
    })
    export class SvgComponent implements OnInit {
    
    link: string = '';
    
    @Input() size: SvgSize | undefined;
    @Input() type: string = '';
    @Input() dropShadow: boolean = true;
    
    constructor() {
    }
    
    ngOnInit(): void {
      this.link = `/assets/images/svgs/${this.type}.svg#${this.type}`;
    }
    

    It’s crucial to remember you can’t just link a file to the SVG. You must add a hash tag and the name of your id to the end of the file name after the file extension. You can save on http requests if you house multiple SVGs in one file, aka sprites. But you must use unique ids for each SVG in the file.

    Also, if you want to add classes to apply styles that fit exactly to the shape of the SVG like drop shadows or borders, you have to add them directly to the SVG element or else they will be applied to the component host. However, you can define those classes in the component or as a global class.

    svg.component.html

    <svg [ngClass]="{ 'drop-shadow' : dropShadow }" [class]="size ? size : ''" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
      <use [attr.xlink:href]="link" [attr.href]="link" />
    </svg>
    

    I’m specifying the two href attributes because ‘xlink:href’ is being deprecated and is just there for backwards compatibility.

    svg.component.scss

    @import 'variables';
    
    svg {
      width: inherit;
      height: inherit;
    }
    
    .xs {
      width: $icon-xs-sm;
      height: $icon-xs-sm;
    }
    
    .sm {
      width: $icon-sm-sm;
      height: $icon-sm-sm;
    }
    
    .md {
      width: $icon-md-sm;
      height: $icon-md-sm;
    }
    
    .lg {
      width: $icon-lg-sm;
      height: $icon-lg-sm;
    }
    
    @media (min-width: $breakpoint-md) {
      .xs {
        width: $icon-xs-md;
        height: $icon-xs-md;
      } 
    
      .sm {
        width: $icon-sm-md;
        height: $icon-sm-md;
      }
    
      .md {
        width: $icon-md-md;
        height: $icon-md-md;
      }
    
      .lg {
        width: $icon-lg-md;
        height: $icon-lg-md;
      }
    }
    

    Don’t forget to set the width and height to ‘inherit’ using the ‘SVG’ selector or else you won’t be able to set them outside of the component.

    In order to get around the problem of not being able to view or set the viewBox per reference, I use art boards with square dimensions when exporting SVGs. That way, I don’t have to worry about getting the exact width/height ratio correct and can easily avoid distorted graphics.

    In order to enforce standardized sizes, I also created different classes for each size. I defined them using variables so different apps that use this component can have their own standardized sizes.

    Example Usage

    Alas, here is an example of how to use the SVG component we just created in a button:

    <button class="inherit" [ngClass]="{ 'active' :  active }" (click)="toggleEdit()">
      <ces-svg size="xs" name="pencil"></ces-svg>
    </button>
    

    The SVG’s styles that we set earlier will automatically inherit those of the button. But they can also be set by adding a class to the SVG component.

    Source Files

    Here is a link to the source files. Please send me any thoughts or ideas for improvement. Thanks!

  • Componentize SVGs in Angular and style them on the fly

    Componentize SVGs in Angular and style them on the fly

    As you probably know, SVGs, or scalable vector graphics, are essential if you’re using simple artwork like icons. But did you know that you can make them into Angular components? In fact, the two libraries I use the most are the ones I created for SVGs and buttons.

    Why should you use SVGs?

    I started using SVGs because of their ability to scale without any loss in resolution and because I could color them through CSS. (This was useful for a part of the gamified interactive lesson I started where you get to pick a character and make it grow or shrink.)

    Note: Only SVGs made with paths and outlines can scale indefinitely. SVGs made with images will get fuzzy.

    SVGs are also super lightweight because they are represented in XML, and you can avoid http requests to fetch them!

    Liberate yourself from SVG libraries

    What I didn’t realize was that my beloved Font Awesome library was costing me almost 20 Lighthouse points and that I didn’t need their large Javascript files to make them into tidy components (instead of unmanageable chunks of text) by turning them into Angular components.

    Note: I still subscribe to Font Awesome because of their unparalleled selection. In fact, all of the icons on the sites/apps I make are thanks to their brilliant illustrators.

    If you end up using their SVGs or make your own using Illustrator, be sure to delete any styles/comments that are part of the SVG, so that you can properly override them.

    Angular components don’t have to use HTML templates

    If you want your own Angular SVG library, you can easily turn them into components by linking the templateUrl parameter of your component to the SVG in your asset library. (Font Awesome offers a library to access their SVGs, but you can avoid unnecessary dependencies and weight to your app by going this route. As an added bonus, this approach lets you declare your SVGs once, instead of having to declare them individually in every app that uses them.)

    svg-astronaut.component.ts

    @Component({
      selector: 'ces-svg-astronaut',
      templateUrl: '../../../../../../src/assets/images/svgs/astronaut.svg',
      styleUrls: ['../../svg.component.scss']
    })
    

    Note: Initially, I was storing the assets directly in my Angular library but then moved the SVGs to my apps’ shared assets folder so that I don’t have to modify my angular.json file to use the assets and so that I could access the SVGs outside of the library.

    The downside to this decision is that the library won’t work outside of the workspace unless you include the assets folder. Please let me know if you have a better solution.

    Be careful on how you link to your SVGs

    You can’t link the SVGs using the usual “src/assets” or “/assets” shortcuts, as they require a direct relative path to your app’s source folder. That’s why I had to use a ridiculously long relative path. (Again, I’m sure there’s a better way to achieve this.)

    Use the same CSS file for all of your SVGs

    I also linked the SVGs to the same CSS file since they all require the same styles, which are required to be able to style them on the fly through the parent that’s using them. By doing so, I just need to update one file to affect all of the components in the future.

    svg.component.css

    svg {
      width: inherit;
      height: inherit;
      fill: inherit;
      background: inherit;
      background-color: inherit;
    }
    
    img {
      width: inherit;
      height: inherit;
    }
    

    Note: Don’t forget to include the components in your module’s exports section so that your app can access them. And import the SVG library into the apps that use them.

    Clean up unused files

    You can delete the html and CSS files that came with your component, as your component won’t be using them.

    Use your new component

    Now, if I want to use an SVG, I just use the component’s selector:

    <ces-svg-astronaut></ces-svg-astronaut>
    

    Because I follow the same naming convention, e.g., prefix-svg-description, I usually don’t have to look up what I called it.

    What if you want to dynamically select the SVG?

    With some use cases, you won’t know ahead of time which SVG you want to select. Because you can’t make part of the selector dynamic, this feature requires setting up a separate general component.

    svg.component.ts

    import { Component, Input } from '@angular/core';
    
    @Component({
      selector: 'ces-svg',
      template: `
          <img src="/assets/images/svgs/{{ type }}.svg" [alt]="type + ' icon'" [title]="title">`,
      styleUrls: [
      './svg.component.scss'
       ]
    })
    export class SvgComponent  {
      @Input() type: string;
      @Input() title:string;
    }
    

    Note: This is why I included styles for “img” in the above CSS. To change the color of the SVG image, you need to use these styles on an element:

    mask: url('/assets/svgs/astronaut');
    background-color: orangered;
    

    Automatically add “alt” tags and dynamically add “title” tags

    I included the “alt” attribute to automatically take the icon’s type with the word “icon” so that I didn’t have to specify them individually. However, I made the “title” attribute a variable in case I wanted to add help text that shows upon hover, which will vary depending on the usage.

    Use the general SVG component

    Now, you can use the same selector and specify which icon you want to use by passing in an icon type. You only have to set up this component once, even if you add/delete SVGs to your library.

    <ces-svg type="astronaut">
  • How to create a social media component in Angular for all of your users

    How to create a social media component in Angular for all of your users

    Using Angular means you never have to repeat your code again! For example, I created a social media component that is account neutral so that it can be reused over and over again, even if the user has completely different accounts. I’ve outlined the steps below:

    Step 1: Create an interface called Social Media

    You should take advantage of Typescript’s strong typing capability to indicate what parameters the user will need to provide. I chose to include “link” for a hyperlink to the user’s account and “user” for the account holder’s name.

    export interface SocialMedia {
      link:string,
      user:string
    }
    

    Step 2: Create a social media component

    Use variables in your component’s HTML so that the hyperlink and icon will automatically be created for the user.

    <div class="social-media" [ngClass]="{'vertical':vertical}">
      <div *ngIf="facebook" class="social-media-icon">
        <a [href]="facebook.link" target="_blank" rel="noopener" title="view {{ facebook.user }} on facebook"><ces-svg-facebook></ces-svg-facebook></a>
      </div>
      <div *ngIf="twitter" class="social-media-icon">
        <a [href]="twitter.link" target="_blank" rel="noopener" title="view {{ twitter.user }} on twitter"><ces-svg-twitter></ces-svg-twitter></a>
      </div>
      <div *ngIf="linkedIn" class="social-media-icon">
        <a [href]="linkedIn.link" target="_blank" rel="noopener" title="view {{ linkedIn.user }} on linkedIn"><ces-svg-linkedin></ces-svg-linkedin></a>
      </div>
      <div *ngIf="medium" class="social-media-icon">
        <a [href]="medium.link" target="_blank" rel="noopener" title="view {{ medium.user }} on medium"><ces-svg-medium></ces-svg-medium></a>
      </div>
    </div>
    

    Note: You can make your component even more dynamic by substituting the social platform’s name with a variable and filling all values within a for loop, but I chose to write them out so that it’s clearer to see what’s available.

    Additional note: All of the icons on Cloud Engineering Studio were created by componentizing SVGs I purchased with my Font Awesome subscription.

    Step 3: Create Angular Inputs to accept the necessary values

    I added an additional boolean called “vertical” so the user can specify if they want the icons to be displayed inline.

    export class SocialMediaComponent  {
      @Input() facebook:SocialMedia;
      @Input() twitter:SocialMedia;
      @Input() linkedIn:SocialMedia;
      @Input() medium:SocialMedia;
      @Input() vertical:boolean = true;
    }
    

    Step 4: Use the component

    I included the social media component in the footer of my website.

    <ces-social-media ngClass="social-media-footer" [facebook]="{link: 'https://www.facebook.com/cloudengineeringstudio/', user: 'Cloud Engineering Studio' }" [twitter]="{link: 'https://twitter.com/CloudEngineeer', user: 'CloudEngineer'}" [linkedIn]="{link: 'https://www.linkedin.com/company/cloudengineeringstudio', user: 'Cloud Engineering Studio'}" [medium]="{link:'https://medium.com/@yoko_65687', user: 'Yoko Ishioka'}"></ces-social-media>
    

    And voila, here is what will get rendered:

    Angular social media component example

    Here is a link to the code in Github Gist.