Cosmic Blog How to Build a Mobile Product Catalog App Using Angular JS, Ionic and Cosmic JS

How to Build a Mobile Product Catalog App Using Angular JS, Ionic and Cosmic JS

by Ivan Larionov on May 18, 2017

TL;DR

View the codebase and follow installation instructions on GitHub.

In this tutorial I’m going to show you how to create a simple catalog mobile app with Cosmic JS and Ionic Framework.

Prerequisites

You’ll need the node.js, npm and ionic cli pre-installed. Make sure you already have them before start. Please refer to ionic docs how to do this. You need Ionic framework >= 2.0 to run this example, so make sure you have the right Ionic version:

ionic -v

Getting Started

First of all we’ll need to create the ionic project. We’ll use standard tabs template and will modify one tab to keep our Catalog component. So once you’ll have all prerequisites installed, you’ll need to setup the new Ionic project:

ionic start cosmic-demo tabs --v2

After you’ll setup this project you’ll be able to run

ionic serve

And play with your app in browser

Setting up Cosmic JS library

First of all, install Cosmic JS Angular/JavaScript library

npm install cosmicjs --save

Now you should be able to import Cosmic object and perform Cosmic JS API calls like following:

import Cosmic from 'cosmicjs';
const bucket = { slug: 'your-bucket-slug' };

Cosmic.getObjects({ bucket }, (err, res) => {
  console.log(res.objects);
});

Setting up things with Cosmic JS

Create the bucket and remember the bucket name (‘cosmic-ionic’ in our case): 

Than create a new object type named ‘Category’ and please remember the object type slug (‘categories’).

We don’t need any additional settings right now, so just set the name and save object type. After save you’ll be redirected to ‘New Category’ page. Create some categories using this page and save them.

Now create the Product object type using the same method as for categories. But we’ll have one difference - please enter the “Metafields Template” tab and add “Image/File” type metafield with key 'image'. This metafield will store the product image.

The second metafield you’ll need to add is “Single Object Relationship”. Please create such metafield and choose Category as “Object type to choose from”.

Such Product structure allows us to create one-to-many relationship between products and categories.

Once Product object type will be created, please add some demo products and assign them to different categories. Make sure you’ll have more than 5 products in single category - this allow us to test infinite scroll.

Ionic part of the app

Create src/pages/categories_list/categories_list.ts file with the following content:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import Cosmic from 'cosmicjs';
import { ProductsList } from '../products_list/products_list';

@Component({
    selector: 'page-categories',
    templateUrl: 'categories_list.html'
})
export class CategoriesList {
    public categories;

    constructor(
        public navCtrl: NavController
    ) {
        this.categories = [];

        Cosmic.getObjectType({
            bucket: {
                slug: 'cosmic-ionc'
            }
        }, {
            type_slug: 'categories'
        }, (err, res) => {
            this.categories = res.objects.all;
        });
    }
    navToCategory(category) {
        this.navCtrl.push(ProductsList, { title: category.title, id: category._id });
    }
}

Than create a template for CategoriesList component:

<ion-header>
  <ion-navbar>
    <ion-title>
      Categories
    </ion-title>
  </ion-navbar>
</ion-header>
<ion-content padding>
    <ion-list>
        <button ion-item *ngFor="let category of categories" (click)="showProducts()">
            {{ category.title }}
        </button>
    </ion-list>
</ion-content>

Add CategoriesList component to app.module.ts as it’s done with other components like HomePage and set it as first tab for TabsPage component.

What happens here?

Our Categories list component uses Cosmic JS API on its constructor to receive a list of categories we have. It uses two things to achieve the required functionality:

  • Filters objects by Cosmic JS bucket
  • Filters objects by object type

CategoriesList components references ProductsList component - it navigates to products list page once user click on the category item. So we need the ProductsList - component which will show us products list for each particular category. Let’s introduce it!

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import {Http} from '@angular/http';
import { DomSanitizer } from '@angular/platform-browser'
@Component({
    selector: 'page-products-list',
    templateUrl: 'products_list.html'
})
export class ProductsList {
    public products;
    public category_title;
    constructor(
        public navCtrl: NavController,
        public params: NavParams,
        public http: Http,
        private sanitizer: DomSanitizer
    ) {
        this.products = [];
        this.category_title = this.params.get('title');        this.http.get(`https://api.cosmicjs.com/v1/cosmic-ionc/object-type/products/search?metafield_key=category&metafield_value=${this.params.get('id')}`).subscribe((resp) => {
            let data = resp.json();
            if (data.objects) {
                this.products = data.objects;
            }
            else {
                this.products = [];
            }
        });
    }
    getImageUrl(product) {
        let url = product.metafields.find((v) => { return (v.key == 'image') }).value;
        return `https://cosmicjs.imgix.net/${url}`;
    }
    sanContent(product): any {
        return this.sanitizer.bypassSecurityTrustHtml(product.content);
    }

}

And here we have the ProductsList template:

<ion-header>
  <ion-navbar>
    <ion-title>
      {{ category_title }}
    </ion-title>
  </ion-navbar>
</ion-header>
<ion-content padding>
    <ion-card ion-item *ngFor="let product of products">
        <img [src]="getImageUrl(product)" alt="">
        <ion-card-content>
            <ion-card-title>{{ product.title }}</ion-card-title>
            <div class="white-space-normal" [innerHTML]="sanContent(product)"></div>
        </ion-card-content>
    </ion-card>
</ion-content>

What’s happening here?

Cosmic JS JavaScript library doesn’t provide any method to filter objects by their properties, but REST API does. That’s why we’re doing a HTTP request to Cosmic JS API using Angular Http module.

In this case request URL should look like the following:

https://api.cosmicjs.com/v1/BUCKET_NAME/object-type/OBJECT_TYPE_SLUG/search?metafield_key=CATEGORY_OBJECT_TYPE_SLUG&metafield_value=CATEGORY_OBJECT_ID

The second interesting thing we have to look at is getImageUrl function. Image is a part of product metadata, that’s why it’ll be an item of metafields array for each API response object. Our goal is to extract the required metafieldsarray item (with key field equals to ‘image’ - the key we’ve entering during metafield creation). This array item will also have value key - it’s the image file name, we’ll need to prepend it with https://cosmicjs.imgix.net/ to get full image URL.

We’re using Angular 4 here, that’s why we have to use DomSanitizer to display HTML markup received from Cosmic JS API.

Conclusion

Cosmic JS allows us to quickly start mobile application development without thinking too much about backend and API. Generally, everything can be done using your Ionic/Angular developers and would save you a lof of time and money. Any backend/API entities can be quickly added/removed or modified to meet your project requirements.

You may also like


In this episode of the Cosmic JS Developer Spotlight Series, we chatted with Lydia Hallie, remote software developer and active contributor on Dev.to. She has been getting a lot of attention for her easy-to-follow (and beautifully visual!) educational resources for JavaScript. Follow Lydia on Twitter, GitHub, LinkedIn, and enjoy the conversation.

The Cosmic Community focuses on providing helpful resources to equip developers and content creators with the inspiration and know-how to build apps faster, together. In this installment of the Cosmic JS Developer Spotlight Series, we sat down with Quincy Larson, the developer and famed teacher behind freeCodeCamp.org. Follow Quincy on Twitter, Medium, GitHub or LinkedIn, and enjoy the Q/A.

In this installment of the Cosmic JS Developer Spotlight Series, we sat down with Jamie Introcaso, an experienced Software Developer residing in Charlotte, North Carolina. Jamie is an active member of the Cosmic JS Community and recently wrote a blog detailing his migration from WordPress to Cosmic JS. With more community projects on the way, we're excited to interview one of our own for this Spotlight. šŸ˜Ž Follow Jamie on his Cosmic-powered website, Twitter and LinkedIn and enjoy the conversation.

In this installment of the Cosmic JS Developer Spotlight Series, we sat down with Ben Hong, a Senior Front End Engineer residing in Washington, D.C. Ben wears several hats, first as a Front End Engineer at GitLab, as well as being an active Google Developer Expert and Vue.js community partner. He's also put some work into VuePress, one of the newest static site generator for Vue.js projects.

At Cosmic, it's our mission to help teams of developers and content creators build great content-powered apps together. We're happy to announce the new Additional Users Add-On to offer a flexible pricing option for growing teams.

Extensions are a powerful component of the Cosmic JS that allow you to create custom views in your Bucket Dashboard. We've recently made some updates to make using this feature even better.

Ready to Get Started?

No payment info required.
Start Now   Contact Sales