Cosmic JS Blog Stay tuned for community news, company announcements and updates from the Cosmic JS team.

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


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


Today we are announcing a new role, Contributor, which gives you the power to collaborate on content in an entirely new way.

In this Cosmic JS Developer Spotlight, we sat down with Devin Otway, a Software Engineer in San Francisco who currently works as a frontend engineer at Postmates. Devin recently launched a blog called Hacking Depression on Cosmic JS. Check him out on  Twitter  or  LinkedIn , and enjoy the Q/A.

You can now add a link for your writers to be able to preview Object content.  By setting up your Preview links on your Object Types, your writers will easily be able to preview changes to content in draft or published state.

Variety is the spice of life and it is essential to flexible content management.  Currently I'm seeing the trend of data storage move from relational to on-the-fly structures.  Relational databases like MSSQL and MySQL are being less favored and more developers are choosing to move to NoSQL databases like MongoDB.  By more developers I include myself because this is a very flexible and intuitive way to store data.  Key / Value, or as I like to call on-the-fly, content storage is the next stage of content management.  Relational structures bind where on-the-fly sets free.  This is the theory behind Cosmic JS metafields.

Content items are like people in that they come in all shapes, sizes and colors.  Cosmic JS objects allow you to create metafields which give you the power to add on-the-fly key / value pairs.  Create infinite metafields and drag and drop them into parent / child relationships. 

I find it so much easier to keep track of my key / value pairs per object rather than managing a relational schema.  I believe this is the new way of on-the-fly content management that will allow for flexibility and scalability of future content.

We are excited to announce that you can now use all of the Cosmic JS features in a full demo before signing up for an official Cosmic JS account.

In this Spotlight we are focusing on Jon Bloomer, who recently launched the Cosmic JS-powered website for his business Tone Temple.  Jon took some time to answer a few questions about his business, his development process and some of his favorite non-dev rockstars.