My cheat sheet
Here are some steps to build a Clarity Angular App :-)
- Step 0: Requirements installation
- Step 1: Build a new app
- Step 2: Add component and routing
- Step 3: Add a data model
- Step 4: Add Services
- Step 5: Add Clarity component to display data
- Step 6: Create a small Web Server in Go
- Step 7: Bundle everything in a docker image
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>
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