My cheat sheet

Share on:

Here are some steps to build a Clarity Angular App :-)

Step 0: install Node.js, Angular and GoLang on Mac

1brew install node
2npm install -g @angular/cli

For Go, check out https://golang.org/doc/install

Step 1: build a new app

1ng new my-app --routing=false --style=css && cd my-app && ng add @clr/angular
2code . # if Visual Studio Code is installed
3ng serve --live-reload --open

Step 2: add components and routing

1ng generate module app-routing --flat --module=app
2ng generate component comp1
3ng generate component comp2

app-component.html

 1<div class="main-container">
 2  <header class="header header-6">
 3    <div class="branding">
 4      <a href="javascript:void(0)">
 5        <clr-icon shape="vm-bug"></clr-icon>
 6        <span class="title">Project Clarity</span>
 7      </a>
 8    </div>
 9  </header>
10  <div class="content-container">
11    <div class="content-area">
12      <router-outlet></router-outlet>
13    </div>
14    <clr-vertical-nav>
15      <a clrVerticalNavLink routerLink="./comp1" routerLinkActive="active">
16        <clr-icon clrVerticalNavIcon shape="dashboard"></clr-icon>
17        Comp1
18      </a>
19      <a clrVerticalNavLink routerLink="./comp2">
20        <clr-icon clrVerticalNavIcon shape="vm"></clr-icon>
21        Comp2
22     </a>
23    </clr-vertical-nav>
24  </div>
25</div>

in app-routing.module.ts:

 1import { NgModule } from '@angular/core';
 2import { CommonModule } from '@angular/common';
 3import { Comp1Component } from './comp1/comp1.component';
 4import { Comp2Component } from './comp2/comp2.component';
 5import { RouterModule, Routes } from '@angular/router';
 6
 7const routes: Routes = [
 8  { path: 'comp1', component: Comp1Component },
 9  { path: 'comp2', component: Comp2Component },
10];
11
12@NgModule({
13  declarations: [],
14  imports: [
15    CommonModule,
16    RouterModule.forRoot(routes)
17  ],
18  exports: [ RouterModule ]
19})
20export class AppRoutingModule { }
21

Step 3: add a data model

1touch models.ts
1export interface Cat {
2    text: string;
3}

Step 4: add services

1ng generate service cats

in cats.service.ts:

 1import { Injectable } from '@angular/core';
 2import { Observable, of } from 'rxjs';
 3import { Cat } from './models';
 4import { HttpClient, HttpHeaders } from '@angular/common/http';
 5
 6@Injectable({
 7  providedIn: 'root'
 8})
 9export class CatsService {
10
11  constructor(private http: HttpClient) { }
12
13  getCats(): Observable<Cat[]> {
14    return this.http.get<Cat[]>("https://cat-fact.herokuapp.com/facts")
15  }
16}

in app.module.ts:

1
2import { HttpClientModule } from '@angular/common/http';
3
4@NgModule({
5  imports: [
6    HttpClientModule,
7  ],
8})
9

in comp1.component.ts:

 1import { Component, OnInit } from '@angular/core';
 2import { CatsService } from '../cats.service';
 3import { Cat } from '../models';
 4
 5@Component({
 6  selector: 'app-comp1',
 7  templateUrl: './comp1.component.html',
 8  styleUrls: ['./comp1.component.css']
 9})
10export class Comp1Component implements OnInit {
11
12  constructor(public catsService: CatsService) { }
13
14  cats: Cat[] = [];
15
16  ngOnInit() {
17    this.catsService.getCats().subscribe((data) => this.cats = data)
18  }
19
20}
21

Step 5: add Clarity component to display data

in comp1.component.html:

 1<p>comp1 works!</p>
 2
 3<clr-datagrid>
 4    <clr-dg-column>Cat Facts</clr-dg-column>
 5  
 6    <clr-dg-row *ngFor="let cat of cats">
 7      <clr-dg-cell>{{cat.text}}</clr-dg-cell>
 8    </clr-dg-row>
 9  
10    <clr-dg-footer>{{cats.length}} cat facts</clr-dg-footer>
11</clr-datagrid>

My App

Step 6: create a small Web Server in Go

1mkdir -p ./server
2cd server
3go mod init antoine
4touch main.go
 1package main
 2
 3import (
 4	"github.com/gin-gonic/gin"
 5
 6	"path"
 7	"path/filepath"
 8)
 9
10func main() {
11	router := gin.Default()
12
13	router.NoRoute(func(c *gin.Context) {
14		dir, file := path.Split(c.Request.RequestURI)
15		ext := filepath.Ext(file)
16		if file == "" || ext == "" {
17			c.File("./index.html")
18		} else {
19			c.File("./" + path.Join(dir, file))
20		}
21
22	})
23
24	err := router.Run(":80")
25	if err != nil {
26		panic(err)
27	}
28}
 1go build
 2ng build --prod
 3mv antoine ./dist/my-app
 4cd ./dist/my-app
 5./antoine
 6
 7adeleporte@adeleporte-a01 my-app % ./antoine
 8[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
 9
10[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
11 - using env:   export GIN_MODE=release
12 - using code:  gin.SetMode(gin.ReleaseMode)
13
14[GIN-debug] Listening and serving HTTP on :80
15[GIN] 2021/01/25 - 17:02:33 | 304 |     843.929µs |             ::1 | GET      "/"
16[GIN] 2021/01/25 - 17:02:33 | 200 |    5.702677ms |             ::1 | GET      "/runtime-es2015.cdfb0ddb511f65fdc0a0.js"
17[GIN] 2021/01/25 - 17:02:33 | 200 |    10.11552ms |             ::1 | GET      "/styles.f763236cada916dd7938.css"
18[GIN] 2021/01/25 - 17:02:33 | 200 |    5.357246ms |             ::1 | GET      "/polyfills-es2015.ffa9bb4e015925544f91.js"
19[GIN] 2021/01/25 - 17:02:33 | 200 |    8.684829ms |             ::1 | GET      "/main-es2015.c04813a259ecd0c49d48.js"
20[GIN] 2021/01/25 - 17:02:33 | 200 |    9.210793ms |             ::1 | GET      "/scripts.b41015bd1035aa6847f4.js"
21[GIN] 2021/01/25 - 17:02:33 | 200 |     745.624µs |             ::1 | GET      "/favicon.ico"
22

Step 7: bundle everything in a docker image

1touch Dockerfile
2
 1FROM golang:latest as builder
 2
 3LABEL maintainer="Antoine Deleporte <adeleporte@vmware.com>"
 4
 5WORKDIR /app
 6
 7COPY server/go.mod server/go.sum ./
 8
 9RUN go mod download
10
11COPY server .
12
13RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
14
15FROM alpine:latest  
16
17RUN apk --no-cache add ca-certificates
18
19WORKDIR /root/
20
21COPY --from=builder /app/main .
22
23COPY dist/my-app .
24
25EXPOSE 80
26
27CMD ["./main"]
 1docker build  -t adeleporte/my-app .
 2
 3Sending build context to Docker daemon  335.1MB
 4Step 1/14 : FROM golang:latest as builder
 5 ---> 5f46b413e8f5
 6Step 2/14 : LABEL maintainer="Antoine Deleporte <adeleporte@vmware.com>"
 7 ---> Using cache
 8 ---> 7a87c5261969
 9Step 3/14 : WORKDIR /app
10 ---> Using cache
11 ---> d2966e96f2a6
12Step 4/14 : COPY server/go.mod server/go.sum ./
13 ---> Using cache
14 ---> 14b26c1beb91
15Step 5/14 : RUN go mod download
16 ---> Using cache
17 ---> ceaf8bdb094c
18Step 6/14 : COPY server .
19 ---> 84f589d27e31
20Step 7/14 : RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
21 ---> Running in b0bff9e3e2a6
22Removing intermediate container b0bff9e3e2a6
23 ---> 77d0de075c47
24Step 8/14 : FROM alpine:latest
25 ---> 389fef711851
26Step 9/14 : RUN apk --no-cache add ca-certificates
27 ---> Using cache
28 ---> b76400e5614f
29Step 10/14 : WORKDIR /root/
30 ---> Using cache
31 ---> 948f33f39270
32Step 11/14 : COPY --from=builder /app/main .
33 ---> 164380f6ce76
34Step 12/14 : COPY dist/my-app .
35 ---> 50ae351a17f9
36Step 13/14 : EXPOSE 80
37 ---> Running in 7f24383dae0f
38Removing intermediate container 7f24383dae0f
39 ---> 21c0ff0499c4
40Step 14/14 : CMD ["./main"]
41 ---> Running in 9e55a07fe09d
42Removing intermediate container 9e55a07fe09d
43 ---> ee88bd66f307
44Successfully built ee88bd66f307
45Successfully tagged adeleporte/my-app:latest
46
47docker run -p 80:80 -l test adeleporte/my-app
48docker push adeleporte/my-app

DISCLAIMER: The views and opinions expressed on this blog are our own and may not reflect the views and opinions of our employer