Build a Simple Progress Bar Component in Ionic 2 & 3



·

Creating your own custom components for Ionic 2 applications is a lot easier than it might seem initially. You do it all the time already because each page you add to your application is a custom component. Take the HomePage component that the Ionic CLI generates by default as an example, that looks something like this:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({

  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

}

Technically, this sets up a component that we could use by adding the selector page-home to our templates like this:

<page-home></page-home>

This would inject the component wherever we place that tag, which means that contents of the home.html file would be displayed wherever we place that tag and it could also make use of the logic in the home.ts file. Of course, we do not actually do this for pages in Ionic 2. We never actually manually render out pages in our Ionic 2 applications like this (even though they are just components like any other component), instead, we use Ionic’s built in navigation methods. My point is that if you know how to build a basic page in Ionic 2, you already have most of the knowledge to build your own custom components.

In this tutorial, we are going to build a custom progress bar component that we can use in an Ionic 2 application. This progress bar will have an input property that can be set to control the progress bar. It will look something like this:

Ionic 2 Progress Bar

Once it has been completed, we will be able to use this component anyway where we want in the application, as many times as we want, or even in completely different applications, just by using the following syntax:

<progress-bar [progress]="loadProgress"></progress-bar>

This is why creating a custom component can be preferable to building the functionality directly into your pages. It makes the code for your pages a lot cleaner and allows for much easier reuse (rather than having to copy and paste a bunch of code all the time).

Before We Get Started

Last updated for Ionic 3.2.1

Before you go through this tutorial, you should have at least a basic understanding of Ionic 2 concepts. You must also already have Ionic 2 set up on your machine.

If you’re not familiar with Ionic 2 already, I’d recommend reading my Ionic 2 Beginners Guide first to get up and running and understand the basic concepts. If you want a much more detailed guide for learning Ionic 2, then take a look at Building Mobile Apps with Ionic 2.

Understand Input and Output in Custom Components

As I mentioned in the introduction, if you already have the basics of Ionic 2 down then you already have most the knowledge that you need for building your own custom components. Property binding, event binding, two-way data binding, interpolation, using Ionic’s components, styling – all of these concepts and more are all exactly the same as when you work with them on normal pages in Ionic 2.

One concept you may not come across before attempting to create your own custom components is Input and Output. A component needs a way for data to flow in and flow out. Data can flow into the component (from its parent component) through its @Input, and data can flow out of the component (up to its parent component) through its @Output. We can use property binding to provide a component with input, and we can make the component fire an event to create output.

Setting up @Input and @Output in a component might look like this:

import { Component, Input, Output, EventEmitter } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'my-component',
  templateUrl: 'my-component.html'
})
export class MyComponent {

    @Input('propertyName') myValue;
    @Output() someEvent = new EventEmitter();

    constructor(){

    }

}

If we want to pass in some data to this component now, we can use the someProperty input to do that, like this:

<my-component [propertyName]="someValue"></my-component>

Once we do that, whatever someValue is will be available anywhere inside of our custom component as this.myValue since we set that up using @Input. If we want to trigger an event from within the component then we can just emit some data using the EventEmitter we set up using @Output like this:

this.someEvent.emit({data: someData});

which would then allow us to listen for that even like this:

<my-component [propertyName]="someValue" (someEvent)="doSomething()"></my-component>

For the progress bar component, we will just be using @Input as we have no need to send any data back to the parent component. We just want to be able to supply our progress bar component with a value that it should use to display a certain percentage of progress.

Now that we have that bit of theory out of the way, let’s jump into creating the loading bar component.

1. Generate a New Ionic 2 Application

To start off with, we are going to generate a new Ionic 2 application using the blank template.

Run the following command to generate a new Ionic 2 project:

ionic start ionic2-progress-component blank --v2

Once the project has generated, make it your working directory:

cd ionic2-progress-component

We are also going to use the Ionic CLI to generate a template for our component.

Run the following command to generate the progress bar component:

ionic g component ProgressBar

This will generate the component for us, but we are also going to have to import and declare it in our app.module.ts file.

Modify src/app/app.module.ts to reflect the following:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { ProgressBarComponent } from '../components/progress-bar/progress-bar';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    ProgressBarComponent
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Note that you only need to include the custom component in the declarations array, you don’t need to add it to the entryComponents as well.

2. Create the Component

We’re going to jump straight into the fun bit now and step through creating the progress bar component. Let’s start off by implementing the progress-bar.ts file.

Modify src/components/progress-bar/progress-bar.ts to reflect the following:

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

@Component({
  selector: 'progress-bar',
  templateUrl: 'progress-bar.html'
})
export class ProgressBarComponent {

  @Input('progress') progress;

  constructor() {

  }

}

You’ll notice that this looks pretty similar to the example code I showed you earlier. All we are doing here is setting up an @Input called progress that we will use to control how full the progress bar should be. This is actually all we need to do for this file, the rest of the logic will be handled in the template.

Modify src/components/progress-bar/progress-bar.html to reflect the following:

<div class="progress-outer">
    <div class="progress-inner" [style.width]="progress + '%'">
        {{progress}}%
    </div>
</div>

This is also a pretty simple file. We create a container <div> so that we can apply the appropriate styling to this component later. The interesting part is the inner <div>, we use property binding to bind our progress input to the width property for the element (along with a percentage symbol). So if we give this component an input of 50, it will set the width of that inner <div> to 50%. Then we just render out that value as text inside of the <div>.

That will control how full the progress bar should be, and all we have left to do is add a bit of styling.

Modify src/components/progress-bar/progress-bar.scss to reflect the following:

progress-bar {

    .progress-outer {
        width: 96%;
        margin: 10px 2%;
        padding: 3px;
        text-align: center;
        background-color: #f4f4f4;
        border: 1px solid #dcdcdc;
        color: #fff;
        border-radius: 20px;
    }

    .progress-inner {
        min-width: 15%;
        white-space: nowrap;
        overflow: hidden;
        padding: 5px;
        border-radius: 20px;
        background-color: map-get($colors, primary);
    }

}

All this really does is style the component so that it looks like a loading bar.

3. Use the Component

Our component is finished now, so all we need to do is use it. To do that, you can just use the following syntax in any of your templates:

<progress-bar [progress]="loadProgress"></progress-bar>

This example would bind the progress property to a member variable called loadProgress that would be set up in the TypeScript file. You can even change this loadProgress variable dynamically (as a download is progressing, for example) to create an animated effect like this:

Ionic 2 Progress Bar

Summary

We now have a component that we can easily just drop into any template, in any application, and control it easily. Once you get the hang of creating custom components and identifying when they might be necessary, they can do a lot to make your application much more organised and reusable.

What to watch next...

  • Franz

    Hi Josh,

    great tutorial!!

    I have one question. I wanted to access the value of the progress variable, but it shows “undefined”. If I write the next code:

    export class ProgressBarComponent {
    @Input(‘progress’) progress;

    constructor() {
    console.log(“Progress: ” + this.progress);
    }
    }

    The console shows:

    Progress: undefined

    How can I do this.

    Thanks

    • Malkiat Singh

      You have to pass value to progress
      and then on changes event you check the value of progress

      • Donbelar Goh

        Which object can I use to pass?

  • It’s not working for me, I copied all the codes, the progress bar appears but without animation
    Please help, how can I make that effect ?
    Thanks in advance

  • Frostie Flakes

    Straightforward and elegant!

    Small question. If you insert multiple progress bar components in an ionic page. And you would like to overwrite each component with it’s own unique background color so that you can distinguish the different progress bars. E.g. a red progress bar, a blue progress bar and a yellow progress bar. How would you do this?
    Is there a way to inherit from the main component and adjust some properties as need be? Or would you create a different progress bar component for each color?

  • Jonathan Greisz

    Josh,

    I tried creating my own component and got a binding error. So I tried cutting and pasting and building your component and still get a binding error. Here is the error: Uncaught (in promise): Error: Template parse errors: Can’t bind to ‘progress’ since it isn’t a known property of ‘progress-bar’.

    app.module.ts contains:

    import { ProgressBar } from ‘../components/progress-bar/progress-bar’;

    @NgModule({
    declarations: [
    MyApp,
    PTTDate,
    ProgressBar
    ],

    progress-bar.ts contains:

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

    @Component({
    selector: ‘progress-bar’,
    templateUrl: ‘progress-bar.html’
    })
    export class ProgressBar {

    @Input(‘progress’) progress;

    constructor() {

    }

    }

    progress-bar.html contains:

    {{progress}}%

    What am I missing. Everything seems correct???

    Thanks,
    Jon

    • Emmanuel KOMENAN

      If you use ionic 3 with angular 4 structure and have pages with their own module (example : home.ts, home.html, home.scss, home.module.ts) then declare progressBarComponent in the .module.ts of the page and remove it from app.module.ts

      • Xi Xiao

        Thanks Emmanuel, your tip helped me out.

      • Ashok Kumar

        Thanks, it fixed the issue with ionic 3 and angular 4.

  • Vinay Singh

    There is no animation in progress bar.

  • Steven Scott

    Is there an update to show the animation similar to the sample screen shot? I have mine working except for updating my progress. I can move the values along, but do not get the animation.

  • Jan Klug

    thanks, works fine! except for a small problem…
    when I enter the page with the progress bar via a button with [navPush]=”progressPage” from my root page, it works fine.
    however, when I go to that page from a different origin, via this.navCtrl.push(progressPage), the progress bar doesn’t update – until an alert is triggered or cancelled…

  • Subhadarshani Patra

    Hello,
    I have added the progess bar .it’s working fine but it is showing error while build i.e. ionic cordova build android –prod
    error:
    1. If ‘progress-bar’ is an Angular component, then verify that it is part of this module.

    2. If ‘progress-bar’ is a Web Component then add ‘CUSTOM_ELEMENTS_SCHEMA’ to the’@NgModule.schemas’ of this component to suppress this message.

    I have followed all the steps mentioned in this link.it’s working fine in ionic serve but while build the app it throws the error.

    Please give me any solution on this.

  • Jose Vieira Neto

    Nice!!! Thank’s

  • Arpit Dadheech

    Thanks !! For a Very Good Post.
    I have one Question. Is there any way to make this progress bar circular and show the progress circular in place of straight line.

  • Subhadarshani Patra

    hello,
    I wan to change the progress bar color if the percentage is more than 50 %,how to achieve this?can anyone help me on this.

  • Meiyanatham P

    This example would bind the progress property to a member variable called loadProgress that would be set up in the TypeScript file. How to acheive this? Please anyone help me on this?

  • Tyler Taylor

    I feel like this skips the most important part, the implementation.

  • nissar

    Hi i am trying to create round progress bar using https://github.com/crisbeto/angular-svg-round-progressbar but i am getting error “Uncaught Error: Unexpected value ‘RoundProgressConfig’ imported by the module ‘AppModule’. Please add a @NgModule annotation” . Please could you create example on this

  • Rajesh

    hi, Nice works, thanks a lots.., in Android its working perfect, but for ios how i can write Css ,
    Because its width showing very short