Build a blog with Carbon LDP and Angular – Part 1

In this tutorial, we are going to be creating an awesome blog engine using two great tools: Angular and Carbon LDP.

This tutorial was inspired by the official one published by the Carbon LDP team in https://carbonldp.com/blog/2018/11/23/build-a-blog-with-carbon-ldp-and-react-part-1/

In order to successfully go through this tutorial, JavaScript and CSS knowledge is required.

Complementary source code is available in carbonldp-angular-blog repository.

In today’s part, we will be focusing on building the UI with Angular and Angular Material by using the Angular CLI.

The end goal

We know building a robust and powerful blog engine (such as WordPress) is not a trivial task, however, with these steps, you will be able to understand the concepts behind building applications with Carbon LDP and Angular.

Create the project skeleton using Angular CLI

Install the Angular CLI

sudo npm install -g @angular/cli

Create the new Angular app

ng new carbonldp-angular-blog

Answer the Angular CLI questions (we will use SCSS as pre-processor)

? Would you like to add Angular routing? (y/N) y
? Which stylesheet format would you like to use? SCSS

Once the scaffolding is done, run following command and this is how your fresh Angular app should look:

# This will run a local server in port 4200 by default, so please visit http:localhost:4200 to see your app

cd carbonldp-angular-blog
ng serve

If you take a look at the project structure, these are the file will appear:

.
├── README.md
├── angular.json
├── e2e
│   ├── protractor.conf.js
│   ├── src
│   └── tsconfig.e2e.json
├── package-lock.json
├── package.json
├── src
│   ├── app
│   ├── assets
│   ├── browserslist
│   ├── environments
│   ├── favicon.ico
│   ├── index.html
│   ├── karma.conf.js
│   ├── main.ts
│   ├── polyfills.ts
│   ├── styles.scss
│   ├── test.ts
│   ├── tsconfig.app.json
│   ├── tsconfig.spec.json
│   └── tslint.json
├── tsconfig.json
└── tslint.json
src/index.html is the app entry point (where everything starts), src/app/main.ts is the “main” file from Angular, src/app is where all our code will usually be.

Add Angular Material

Installation

Since our main goal in this series is to focus on learning how Carbon LDP and Angular can work together, we will be using a set of proven components by Angular Material.

Let’s install our dependencies by following the official Angular Material documentation:

npm install --save @angular/material @angular/cdk @angular/animations

Open src/app/app.module.ts and import there the BrowserAnimationsModule

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserAnimationsModule,
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Import the component modules

Let’s do a quick test using the “Button” module, for doing that, we need to import the corresponding module to our src/app/app.module.ts

import { MatButtonModule } from '@angular/material';
@NgModule({
  declarations: [
  // More components here...
  ],
  imports: [
    // More modules here...
    MatButtonModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Next, open src/app/app.component.html and remove everything except the router-outlet and add your brand new material button as follows:

<button mat-raised-button color="primary">Primary</button>
<router-outlet></router-outlet>

No errors in our console, but our button looks kind of sad… let’s add a material theme to make our material components beautiful.

Open src/styles.scss, and add this line to it:

/* You can add global styles to this file, and also import other style files */
@import "~@angular/material/prebuilt-themes/indigo-pink.css";

Go to your web browser, you should see your “primary” button with a blue background.


One of the easiest ways to add support for icons is by using a font, for doing that, open src/index.html and add a <link /> tag with the reference to the font family with Material Icons, this is how our src/index.html file will be after adding the icons.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>CarbonldpAngularBlog</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">

  <!-- Adding support for icons -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body>
  <app-root></app-root>
</body>
</html>

For alternate ways for adding icons, please visit Angular Material documentation.

Implement a Basic Drawer

It is time to continue building our UI. Let’s create a “Layout” component within,src/components/layout this is really easy if we use the Angular CLI

ng generate component components/layout

The previous command will generate the following files; let’s open the src/app/components/layout/layout.component.html

src/app/components/
└── layout
    ├── layout.component.html
    ├── layout.component.scss
    ├── layout.component.spec.ts
    └── layout.component.ts

Add the Angular Material modules in src/app/app.module.ts

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';

import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';

import {MatButtonModule, MatIconModule, MatSidenavModule, MatToolbarModule, MatNavList} from '@angular/material';
import {LayoutComponent} from './components/layout/layout.component';

@NgModule({
  declarations: [
    AppComponent,
    LayoutComponent,
    MatNavList,
  ],
  imports: [
    BrowserAnimationsModule,
    BrowserModule,
    AppRoutingModule,
    MatButtonModule,
    MatIconModule,
    MatSidenavModule,
    MatToolbarModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

Open src/app/components/layout.component.html and paste this code:

<div class="layout-container" [class.example-is-mobile]="mobileQuery.matches">
  <mat-toolbar color="primary" class="example-toolbar">
    <button mat-icon-button (click)="snav.toggle()">
      <mat-icon>menu</mat-icon>
    </button>
    <h2 class="layout-app-name">CarbonLDP / Angular Blog Engine</h2>
  </mat-toolbar>

  <mat-sidenav-container class="layout-sidenav-container"
                         [style.marginTop.px]="mobileQuery.matches ? 56 : 0">

    <mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'"
                 [fixedInViewport]="mobileQuery.matches" fixedTopGap="56">

      <mat-nav-list>
        <div class="b-button-container">
          <a class="b-button" mat-list-item routerLink=".">
            <i class="b-button__icon material-icons">home</i>
            <span class="b-button__label">Home</span>
          </a>
        </div>

        <div class="b-button-container">
          <a class="b-button" mat-list-item routerLink=".">
            <i class="b-button__icon material-icons">note</i>
            <span class="b-button__label">Blog</span>
          </a>
        </div>
      </mat-nav-list>

    </mat-sidenav>

    <mat-sidenav-content>
      <div class="b-content">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad animi architecto asperiores assumenda deserunt
          dignissimos enim ex, facere laboriosam neque obcaecati possimus qui quia reiciendis soluta, vitae
          voluptatibus?
          Ipsam, veniam!</p>
      </div>

    </mat-sidenav-content>

  </mat-sidenav-container>
</div>

In addition, let’s create some styles in src/app/components/layout.component.scss

.layout-container {
  display: flex;
  flex-direction: column;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

.layout-is-mobile .layout-toolbar {
  position: fixed;
  /* Make sure the toolbar will stay on top of the content as it scrolls past. */
  z-index: 2;
}

.layout-app-name {
  margin-left: 8px;
}

.layout-sidenav-container {
  /* When the sidenav is not fixed, stretch the sidenav container to fill the available space. This
     causes `<mat-sidenav-content>` to act as our scrolling element for desktop layouts. */
  flex: 1;
}

.layout-is-mobile .layout-sidenav-container {
  /* When the sidenav is fixed, don't constrain the height of the sidenav container. This allows the
     `<body>` to be our scrolling element for mobile layouts. */
  flex: 1 0 auto;
}

.b-button-container {

  .b-button {
    display: block;
    min-height: 34px;
    min-width: 145px;
    padding: 5px 10px;
  }

  .b-button__icon {
    margin-top: 5px;
    margin-right: 5px;
    display: block;
    float: left;
  }

  .b-button__label {
    margin-top: 10px;
    display: block;
    float: left;
  }
}

.b-content {
  padding: 20px;
}

And modify the src/styles.scss

/* You can add global styles to this file, and also import other style files */
@import "~@angular/material/prebuilt-themes/indigo-pink.css";

body {
  font-family: Roboto, Arial, sans-serif;
  margin: 0;
}

Checkpoint: let’s see how our app is looking so far and make a commit to our Git repository.

Implement navigation routes

It is time, to start thinking in our navigation routes, for instance, we will have

Leave a Reply

Your email address will not be published. Required fields are marked *