Angular 2 – create a simple eCommerce site

If you work on a eCommerce website, one of the challenges is to extract filter possiblities from products, filter large datasets and update multiple views. I would like to show you how to implement a service in Angular 2, how to filter data and update multiple views.

TL;DR;

Here is the sample project as a download.

The goal is to extract filter possibilities from a dataset of products, display the filters in a sidebar and display the first 20 results of the filtered dataset in a result-list.

First I create my project from the Quick Start Guide of Angular 2.

Additional Dependencies

I would like to have bootstrap available to style the sidebar and result-list component. I open the ./package.json and add bootstrap and jQuery as a dependency.

  • bootstrap is a framework for developing responsive, mobile first websites and depends on jQuery.

Install the dependencies with npm install

Add Bootstrap and Angular 2 Router

I need the Angular 2 router because I would like to have a separate component for the catalog and to show how the service providers have to be configured that I can use events in multiple views.

  • Line 3: an base element to tell the router how to compose navigation URLs (straight from the Routing & Navigation Documentation)
  • Line 6: reference to bootstrap CSS file
  • Line 16: reference to the Angular 2 Router module
  • Line 33: reference to jQuery library
  • Line 34: reference to bootstrap javascript library

Activate the Angular 2 Router

First I am gonna modify the ./app/main.ts file.

To activate the Angular 2 Router, I have to load the ROUTER_PROVIDERS from the angular2/router module and pass it as the second parameter to the bootstrap function.

To bind a different component to a specific route (in my case /catalog) I have to update the main component ./app/app.component.ts.

  • Line 2: import RouteConfig and ROUTER_DIRECTIVES from the angular2/router module
  • Line 3: import the HeaderComponent, it is just a bootstrap navbar to link to the /catalog route
  • Line 4: import the CatalogComponent, it is the main component of the /catalog route
  • Line 9: add the <header-component> selector to render the header on every page
  • Line 10: add the <router-outlet> directive, that is a placeholder for every content that will be generated by a component bound to a route. In my case the content from CatalogComponent for the route /catalog
  • Line 12: pass the ROUTER_DIRECTIVES and the HeaderComponent as directives into the AppComponent
  • Line 15 -17: add a RouterConfig and bind the CatalogComponent to the route /catalog. I also add a name for the route to generate a link in the HeaderComponent

HeaderComponent and generating a link with the Routerlink directive

  • Line 2: import the RouterLink directive from angular2/router module
  • Line 15: use the [routerLink] directive in the template to generate a link to the /catalog route with the name ‘Catalog’ defined in the RouteConfig in ./app/app.component.ts
  • Line 21: pass the RouterLink directive into the HeaderComponent

To test the HeaderComponent, I comment everything out that depends on the CatalogComponent in ./app/app.component.ts.

 

If I now run the application with npm start I see the HeaderComponent and a link that points to the route /catalog.

Angular 2 RouterLink

CatalogComponent, childcomponents and productservice

The CatalogComponent consists of two child components. The SidebarComponent displays all filters (with count) that exists in the list of products. And the CatalogResultListComponent displays the first 20 products of the (filtered) list of products.

I also need a service to get some random products and filter the list of products, I will call it ProductService.

  • Line 2-4: import SidebarComponent, CatalogResultListComponent and ProductService
  • Line 11-12: reference the child components in the template
  • Line 16: pass the child components as directives in the CatalogComponent
  • Line 17: pass the ProductService as Provider into the CatalogComponentthat is important because:
    • when I put the ProductService as Provider in the child components, then every component gets it’s own instance of the service and the event system can not work!
    • make sure that every service that has events that should be subscribed by multiple components is passed as a provider in the parent component!

ProductService and Sample data

The sample data will be represented as an array of ProductModels, so I create the model first in ./app/catalog/product.model.ts.

I also need some kind of generator to make an array of sample products on page load. I create the file ./app/catalog/product.generator.ts.

It is a class with a public static function that returns a random number of products between 10.000 and 20.000. Every product has between 16 and 72 filters, and there is a maximum of 200 filters (max. 200 unique filters in the sidebar).

The filters variable is an array of strings with the format “category:urlName:displayName” e.g. “feature:filter1:Filter1”. I don’t need this for this tutorial, but maybe someone would like to try to group filters in the sidebar or want to save filters in the URL.

Now i am ready to implement the ProductService in the file ./app/catalog/product.service.ts.

  • Line 1: import Injectable to mark the service class for angular2 dependency injection. import EventEmitter, that is basically a wrapper for rxjs observable, we need it to fire events when the product list changes
  • Line 2: import ProductModel for typings
  • Line 3: import ProductGenerator to get a random list of products
  • Line 5: decorator to tell angular2 that this class can be injected via dependency injection
  • Line 11: get the random list of products in the constructor
  • Line 18: returns a Promise and pass the full list of products into the resolve function
  • Line 30: if no filters are passed into the function, emit the event (pass to subscriber) with the full list of products
  • Line 36: if filters are passed into the function, emit the event (pass to subscriber) with a filtered subset of the products

CatalogResultListComponent

The CatalogResultListComponent displays the first 20 products of the (filtered) list of products.

  • Line 1: import Component, OnInit (interface for the init event from Angular 2), OnDestroy (interface for the destroy event from Angular 2), EventEmitter from angular2/core
  • Line 2: import ProductModel for typings
  • Line 3: import ProductService to consume the actual list of products
  • Line 15: iterate through all 20 products in the products variable with the *ngFor directive
  • Line 29: implement the interfaces OnInit and OnDestroy
  • Line 30: local variable to subscribe to the serviceEvent$ from ProductService
  • Line 35: inject the ProductService instance into the Component and assign it to the local variable _service
  • Line 46: Angular 2 OnInit event, required by the OnInit Interface
  • Line 50-52: subscribe to the update event of ProductService to keep result-list in sync
  • Line 57-59: load all products to display the initial list
  • Line 62: Angular 2 OnDestroy event, required by the OnDestroy Interface
  • Line 66: unsubscribe from ProductService event

SidebarComponent

The SidebarComponent displays all filters (with count) that exists in the list of products.

  • Line 1: import Component, OnInit (interface for the init event from Angular 2), OnDestroy (interface for the destroy event from Angular 2), EventEmitter from angular2/core
  • Line 2: import ProductModel for typings
  • Line 3: import ProductService to consume the actual list of products
  • Line 9: iterate through all filters in the displayFiltersvariable with the *ngFor directive
  • Line 13-14: bind the (click) event to the filter() function and pass the displayFilter.id into the filter() function, bind the displayFilter.disabled property to the *ngIf directive to disable/enable the filter
  • Line 24: implement the interfaces OnInit and OnDestroy
  • Line 25: local variable to save the extracted filters
  • Line 26: local variable to subscribe to the serviceEvent$ from ProductService
  • Line 27: local variable to save selected filters
  • Line 29: public variable with all unique filters for the template and change detection
  • Line 31: inject the ProductService instance into the Component and assign it to the local variable _service
  • Line 34: Angular 2 OnInit event, required by the OnInit Interface
  • Line 38-40: subscribe to the update event of ProductService to keep result-list in sync
  • Line 45-47: load all products to display the initial list
  • Line 50: Angular 2 OnDestroy event, required by the OnDestroy Interface
  • Line 54: unsubscribe from ProductService event
  • …: read the comments in the code to understand the business logic
  • Line 156: function is used by template to add or remove filter to the activeFilters variable and filter data set

Result

Ok, I think I’ve finished the task. It is time to test this whole thing. I run npm start.

I see the HomePage, nothing special here. I navigate to the /catalog route by clicking the link in the navbar.

Angular 2 RouterLink

Tadaaaaaaa, Sidebar, Filters, Result-List. Everything I need to filter products.

Angular 2 filter catalog init

And this is how it looks when you activate some filters:

Angular 2 filter catalog active filters

Here is the sample project as a download.

1 comment on “Angular 2 – create a simple eCommerce siteAdd yours →

Comments are closed. You can not add new comments.