Creating reusable components

Just as the coronavirus outbreak taught us to isolate ourselves for our own benefit as well as for the benefit of everyone around us, isolating parts of your code can give you a lot of benefits:

  • smaller code

  • bugs only in one place

  • no code duplication

  • better code structure

Creating a component and (re)using is very simple.

In this tutorial, we will create a component that will mock publishing the current page to social media.

Creating the app

Let’s create a new Ionic Capacitor app and add a folder named components inside the app folder.

> ionic start components blank

Once you are done with adding the folder your project structure will look like this

...
 src
   app
     components
...

Let’s now create a component using by using the Ionic CLI

Generating the component

> ionic generate component components/social-share

This will create all the needed files (.html, .scss, and .ts) and we are ready to add functionality to our component!

// social-share.component.html

<ion-button (click)="onShareClick()">
  <ion-icon 
    slot="icon-only" 
    name="share-social-outline">
  </ion-icon>
</ion-button>

// social-share.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-social-share',
  templateUrl: './social-share.component.html',
  styleUrls: ['./social-share.component.scss'],
})
export class SocialShareComponent {
  @Input() currentPage: string;

  constructor() { }

  onShareClick() {
    alert(`Sharing ${this.currentPage} to the world!`);
  }
}

Now that we have a basic component that uses the @Input() currentPage to know from where it has been called there are just two more things to be done.

Creating a components module

In order to use the component, it has to be declared inside one (and only one) module. If you plan to use a component just on a single page it makes sense to declare it inside that page’s module. However, we expect this component to be used across the app so we will create a components module from which then other parts of our application can use this specific component.

// components.module.ts

import from '@angular/core';
import from '@ionic/angular';

import from './social-share/social-share.component';

const components = [
  SocialShareComponent
];

@NgModule({
  imports: [
    IonicModule
  ],
  declarations: components,
  exports: components
})
export class ComponentsModule { }

Using the component

Let’s open our home.page.html file and add the component.

// home.page.html

<ion-header [translucent]="true">
    <ion-toolbar>
        <ion-title>
            Components
        </ion-title>
    </ion-toolbar>
</ion-header>

<ion-content>
    <app-social-share currentPage="Home"></app-social-share>
</ion-content>

The element app-social-share is the one we have defined as the selector for our component in the social-share.component.ts file. Keep in mind that you can name the selector anything you want but you should stay away from keywords like button, div, etc. Now we only need to run the app and try it out.

> ionic serve

If you followed everything you should now see a blank screen. By opening up the developer console you will see the following message

ERROR Error: Uncaught (in promise): Error: Template parse errors:
'app-social-share' is not a known element:
1. If 'app-social-share' is an Angular component, then verify that it
is part of this module.
2. If 'app-social-share' is a Web Component then add
'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this 
component to suppress this message. ("

<ion-content>
    [ERROR ->]<app-social-share></app-social-share>
</ion-content>
"): ng:///HomePageModule/HomePage.html@9:1
Error: Template parse errors:
'app-social-share' is not a known element:
1. If 'app-social-share' is an Angular component, then verify that 
it is part of this module.
2. If 'app-social-share' is a Web Component then add
'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this 
component to suppress this message. ("

<ion-content>
    [ERROR ->]<app-social-share></app-social-share>
</ion-content>
"): ng:///HomePageModule/HomePage.html@9:1

We get this error message because we didn’t include the ComponentModule into our HomeModule and as a result the HomeComponent has no way of knowing how to render our app-social-share element.

Let’s fix this quickly by adding it.

@NgModule({
  imports: [
    ...
    ComponentsModule
  ],
  ...
})
export class HomePageModule {}

Rerunning the app now will display the button and clicking on the it will execute the click event handler with a simple share function.

final.gif

To end this blog post on a high note (and learn a little more) while still staying on the topic of self isolation and quarantines I thought it might be fun to learn about the origin of quarantines. Instead of me writting another post about it I’ll just drop a line from the CDC’s website.

The practice of quarantine, as we know it, began during the 14th century in an effort to protect coastal cities from plague epidemics. Ships arriving in Venice from infected ports were required to sit at anchor for 40 days before landing. This practice, called quarantine, was derived from the Italian words quaranta giorni which mean 40 days.
— Centers for Disease Control and Prevention

As always, you can check out the full code here.

Until next time,
stay healthy.