Tutorial

Ionic 4.1 & Vue.js: Skeleton Text

Published on March 16, 2019
    Ionic 4.1 & Vue.js: Skeleton Text

    While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

    When we’re loading asynchronous content, it’s advised that you show the user some “skeleton” UI that gives the impression of content being loaded. Let’s use ion-skeleton-text to show how we’d handle this inside of Ionic!

    Inside of an Ionic project we’d traditionally have to accomplish this ourselves with CSS or a third party library. Thankfully, the latest update inside of Ionic 4.1 Hydrogen brings us ion-skeleton-text which we can use to display skeleton content.

    Ionic Vue + Skeleton Text

    We’ll be looking at this with the context of a Vue.js project, but as Ionic is built with Stencil, the underlying principles are framework-agnostic.

    To get started, ensure you have Node.js installed on your machine. Then, run the following in your terminal:

    $ npm install -g @vue/cli
    
    $ vue create vue-ion-skeleton
    
    > default project setup
    
    $ npm install @ionic/core @ionic/vue
    

    We then need to set up IonicVue inside of our project inside of main.js. We’ll also be importing the basic styles that Ionic requires from @ionic/core

    main.js
    import Vue from 'vue';
    import App from './App.vue';
    import '@ionic/core/css/core.css';
    import '@ionic/core/css/ionic.bundle.css';
    
    import IonicVue from '@ionic/vue';
    
    Vue.use(IonicVue); 
    
    Vue.config.productionTip = false;
    
    new Vue({
      render : (h) => h(App)
    }).$mount('#app');
    

    At this stage, we can test that everything works correctly by creating a bare bones Ionic application inside of App.vue:

    App.vue
    <template>
      <ion-app>
        <ion-header>
          <ion-toolbar color="danger">
            <ion-title>S C A R Y</ion-title>
          </ion-toolbar>
        </ion-header>
        <ion-content>
          <ion-card>
            <img src="https://images.unsplash.com/photo-1513681955987-968b5455d7d7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=933&q=80"/>
            <ion-card-header>
              <ion-card-subtitle>Spooky, Scary</ion-card-subtitle>
              <ion-card-title>Skeleton</ion-card-title>
            </ion-card-header>
            <ion-card-content>
              Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv ingdead.
            </ion-card-content>
          </ion-card>
        </ion-content>
      </ion-app>
    </template>
    
    <script>
    
    export default {
      name: 'app',
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

    Scary, Spooky, Ionics.

    Now that we’ve created a bare bones application, let’s move on to our ion-skeleton-text example:

    Skeleton UI

    For example’s sake, let’s say we wanted to load numerous spooky todos and each one comes from our API with varying data.

    If our user was at a location with bad WiFi (say, a coffee shop like the one I’m in right now), it’d be futile to expect that this data will appear instantaneously.

    What do we do? Display skeleton data of course!

    Let’s implement this inside of our application. We’ll use the json-placeholder API to get data from an API and use ion-skeleton-text as a UI buffer until our data arrives.

    <template>
      <ion-app>
        <ion-header>
          <ion-toolbar color="danger">
            <ion-title>S C A R Y T O D O S</ion-title>
          </ion-toolbar>
        </ion-header>
        <ion-content>
          <ion-list v-if="todos.length > 0">
            <ion-item v-for="todo in todos" :key="todo.id">
              <ion-label>{{todo.title}}</ion-label>
            </ion-item>
          </ion-list>
          <ion-list v-else>
            <ion-item v-for="i in 20" :key="i">
              <ion-label>
                <ion-skeleton-text animated>
                </ion-skeleton-text>
              </ion-label>
            </ion-item>
          </ion-list>
        </ion-content>
      </ion-app>
    </template>
    
    <script>
    
    export default {
      name: 'app',
      data() {
        return {
          todos: []
        }
      },
      created() {
        setTimeout(
          () => (
            this.getDataFromAPI()
            ), 3000)
      },
      methods: {
        async getDataFromAPI() {
          try {
            const req = await fetch('https://jsonplaceholder.typicode.com/todos')
            this.todos = await req.json()
          }
          catch(e) {
            console.error(`Error: ${e}`)
          }
        }
      }
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    
    </style>
    

    Let’s take a deep dive into what’s happening here:

    1. Firstly, we’re getting access to a list of todos by making a fetch call to the json-placeholder API. This is done via the getDataFromAPI method that we’ve created.
    2. We’re then calling the getDataFromAPI method inside of the created hook inside of a setTimeout with a 3 second delay. This mirrors a moderate speed internet connection and gives us enough time to see our skeleton text in action.
    3. The use of ion-skeleton-text inside of our v-else block allows us to use the Ionic component that would otherwise replace the skeleton component, thus, keeping as much as the original styling as possible.

    Note: We’re taking advantage of the animated attribute within the ion-skeleton-text to animate this on screen. You’ll see what it looks like when it’s not animated later in this article.

    This gives us the following magical piece of UI:

    Results of our Ionic Skeleton project

    Other Examples

    The great thing about the ion-skeleton-text component is that it’s super flexible! We can use the width style attribute to change how it looks on screen.

    Let’s add a little bit of randomness to our ion-skeleton-text:

    <ion-list v-else>
      <ion-item v-for="i in 20" :key="i">
        <ion-label>
          <ion-skeleton-text :style="`width: ${(80 + Math.random () * Math.floor(240))}px;`">
          </ion-skeleton-text>
        </ion-label>
      </ion-item>
    </ion-list>
    

    Results of our Ionic Skeleton project with randomness

    Summary

    Tada! 🎉 Now we can make awesome “loading” UIs in places where the spinner doesn’t make sense. It’s a great way to replicate how text-based parts of your components will look white asynchronously loading data.

    The source code for this article is available here: Source code

    Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

    Learn more about us


    About the authors

    Still looking for an answer?

    Ask a questionSearch for more help

    Was this helpful?
     
    Leave a comment
    

    This textbox defaults to using Markdown to format your answer.

    You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Get our biweekly newsletter

    Sign up for Infrastructure as a Newsletter.

    Hollie's Hub for Good

    Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

    Become a contributor

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    Welcome to the developer cloud

    DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

    Learn more
    DigitalOcean Cloud Control Panel