Angular Dashboard Tutorial with Cube.js
Tags: tutorials, javascript, opensource, webdev
Published: 2019-05-09 14:58:38

---
title: Angular Dashboard Tutorial with Cube.js
published: true
cover_image: https://thepracticaldev.s3.amazonaws.com/i/49k9ob9wxsth01hndisu.png
description: Angular Dashboard Tutorial with Cube.js
tags: tutorials, javascript, opensource, webdev
canonical_url: https://cube.dev/blog/angular-dashboard-tutorial-with-cubejs/
---

Almost any website has some embedded analytics. You can find usage charts for every public Github repository or any social network today. [Cube.js](https://github.com/statsbotco/cubejs-client) is designed to help developers build such analytical applications. It solves a plethora of different problems every production-ready analytic application needs to solve: analytic SQL generation, query results caching and execution orchestration, data pre-aggregation, security, and API for query results fetch.

We recently covered [how to build](https://cube.dev/blog/cubejs-open-source-dashboard-framework-ultimate-guide/) an analytic dashboard with Cube.js and React, but what about Angular? Starting with version 0.8.4, the Cube.js Client ships with an Angular module for easy integration.
Today I will show you how to build an analytical dashboard using [Angular](https://angular.io/), [Cube.js](https://cube.dev), and [ng2-charts](https://valor-software.com/ng2-charts/). 

You can find [a final dashboard here](https://statsbotco.github.io/cubejs/angular-dashboard/) and a CodeSandbox with the source code below.

{% codesandbox cs1kg %}


## Setting up a Cube.js Backend
We covered this topic in other tutorials, so if you already have your Cube.js backend set up and running, you can skip this section.

You can install Cube.js CLI, which is used for various Cube.js workflows, via NPM or Yarn.

```bash
npm install -g cubejs-cli
```

Let's prepare a Cube.js Backend to serve data for the dashboard we're building. Cube.js supports many databases and deployment options. You can learn more about it [in the documentation](https://cube.dev/docs). For this tutorial, we’ll use a Postgres database and deploy Cube.js to Heroku. Let's create a new Cube.js application using the CLI we just installed.

```bash
cubejs new ng-demo -d postgres
cd ng-demo
```

In case you don't have a database for the dashboard yet, you can download our demo e-commerce dataset for Postgres.

```bash
curl http://cube.dev/downloads/ecom-dump.sql > ecom-dump.sql
createdb ecom
psql --dbname ecom -f ecom-dump.sql

```

The next step is to define a data model. In a production application, you most likely will have multiple schema files, but for our demo app we are going to have only one cube. If you're not familiar with Cube.js data schema, there's an in-depth tutorial [here](https://cube.dev/docs/getting-started-cubejs-schema).

```javascript
cube(`Users`, {
  sql: `SELECT * FROM users`,

  measures: {
    count: {
      sql: `id`,
      type: `count`
    }
  },

  dimensions: {
    city: {
      sql: `city`,
      type: `string`
    },

    signedUp: {
      sql: `created_at`,
      type: `time`
    },

    companyName: {
      sql: `company_name`,
      type: `string`
    }
  }
});
```

Cube.js uses data schema to generate and execute SQL in the connected database. We can test it out by sending a sample request to the Cube.js REST API endpoint.

```bash
curl \
 -H "Authorization: EXAMPLE-API-TOKEN" \
 -G \
 --data-urlencode 'query={"measures":["Users.count"]}' \
 http://localhost:4000/cubejs-api/v1/load
```

You can learn more about the Cube.js Query format [here](https://cube.dev/docs/query-format).

Finally, let’s deploy our backend to Heroku:

```bash
git init
git add -A
git commit -am "Initial commit"
heroku create cubejs-ngx-demo
git push heroku master
```

You can find full deployment guide in the [documentation](https://cube.dev/docs/deployment#heroku).

## Dashboard

Now, when we have a functional backend running, we can move to the next part—building a dashboard. Cube.js has an Angular binding, which doesn’t provide any visualization itself, but is designed to work with any charting library. This way it provides great flexibility for developers to build unique and custom user experiences. 

First, install ng-cli if you don't have it already: 

```bash
npm install -g angular/cli
```

Let's create a new Angular app using SCSS templates:

```bash
ng new ng-demo-dashboard -s scss
```

We'll be using an ng2-charts library, which is an Angular wrapper for Chart.js, to draw charts. The Cube.js Angular Client will be used to load the data from the backend, and finally [Bootstrap](https://getbootstrap.com/) will provide us with some nice styling. Let’s add these dependencies:

```bash
npm install -s ng2-charts @cubejs-client/core @cubejs-client/ngx moment
# or
yarn add ng2-charts @cubejs-client/core @cubejs-client/ngx moment
```

Next, add the required modules to the app.module.ts file:

```javascript
const cubejsOptions = {
  token:
    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.K9PiJkjegbhnw4Ca5pPlkTmZihoOm42w8bja9Qs2qJg",
  options: {
    apiUrl: "https://react-query-builder.herokuapp.com/cubejs-api/v1"
  }
};

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    ChartsModule,
    CubejsClientModule.forRoot(cubejsOptions)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
```

Now we're finished with our app setup. Let's create a chart component:

```bash
ng generate component chart
```

Add some style and an element for ng2-charts:

```html
<div class="card">
  <div class="card-body">
    <h5 class="card-title">{{ title }}</h5>
    <div class="card-text">
      <div *ngIf="ready === false" class="d-flex justify-content-center text-dark">
        <div class="spinner-border" role="status">
	  <span class="sr-only">Loading...</span>
	</div>
      </div>
      <canvas *ngIf="ready && showChart" baseChart height="300" [datasets]="chartData" [labels]="chartLabels" [options]="chartOptions"
			 [colors]="chartColors" [chartType]="chartType"></canvas>
      <h1 *ngIf="ready && !showChart" height="300">{{ chartData }}</h1>
    </div>
  </div>
</div>

```

Let's get the data for our chart. We need to define the inputs, which we'll pass to the ngx-chart component to allow customization:

```typescript
@Input() chartType;
@Input() query;
@Input() title;

public chartData;
public chartLabels;
public chartOptions: any = {
  responsive: true
};
public chartColors;
```

To gather the data, we'll add an input for the query and use the Cube.js [Angular watch API](https://cube.dev/docs/@cubejs-client-ngx#api):

```typescript
constructor(private cubejs: CubejsClient) {}

ngOnInit() {
  this.querySubject = new Subject();
  this.resultChanged = this.resultChanged.bind(this);
  this.cubejs
    .watch(this.querySubject)
    .subscribe(this.resultChanged, err => console.log("HTTP Error", err));

  this.querySubject.next(this.query);
}
```

This will allow us to get and display new data every time the query changes. Now let's create a simple dashboard in our app.component: 
```html
<div class="container-fluid">
  <div class="row">
    <div class="col-sm-4">
      <app-chart chartType="singleValue" [query]="usersQuery" title="Total Users"></app-chart>
    </div>
    <div class="col-sm-4">
      <app-chart chartType="singleValue" [query]="ordersQuery" title="Total Orders"></app-chart>
    </div>
    <div class="col-sm-4">
      <app-chart chartType="singleValue" [query]="shippedOrdersQuery" title="Shipped Orders"></app-chart>
    </div>
  </div>
  <div class="row">
    <div class="col-sm-6">
      <app-chart chartType="line" [query]="lineChartQuery" title="New Users Over Time"></app-chart>
    </div>
    <div class="col-sm-6">
      <app-chart chartType="stackedBar" [query]="stackedBarChartQuery" title="Orders by Status Over time"></app-chart>
    </div>
  </div>
</div>
```

And it's done! You can find [the resulting dashboard here](https://statsbotco.github.io/cubejs/angular-dashboard/) and a codesandbox demo [here](https://codesandbox.io/s/cubejs-client-ngx-demo-cs1kg?fontsize=14).