An Introduction to Nebular by Akveo — #Nebular101 Pt. 1

Glovory Tech
8 min readJul 23, 2020

--

Illustration by Teddy Tri Murdianto

Do you ever use one UI library that provides you with all-in-one supporting? Here is one of the Customizable Angular UI Library with many UI Components, themes, Auth, and Security modules. Nebular, one of the UI Library by Akveo based on Eva Design System. Nebular using ngx-admin template to support UI Components and you can use Eva Colors as a color generator to customize ‘your color palette’ or ‘schemes color’ if necessary.

https://akveo.github.io/nebular/

Nebular let you choose which theme you like or equate with a design that has been provided. You can customize all style components using SCSS, whether you customize them as a global or specific component.

Based on the documentation, there are two ways to install Nebular. First, you can install Nebular manually on your project by CLI and you can follow that documentation. And the other one is using Starter Kit, therefore in this part, we will customize that starter kit until ready to use for development.

Installation

1. For the first, clone the starter kit.

git clone https://github.com/akveo/ngx-admin.git

2. Install the dependency

cd ngx-admin && npm install
Make sure that all dependencies are successfully installed without errors.

3. Run the starter kit
Here, you will get some demo as well as this page. As you can see at the picture below, Nebular let you make web app more interactive with supporting RTL, many themes, and Backend integration (click here to see starter kit bundle with backend integration)

4. Customizing theme based on your brand color with Eva Color Design

You also can use the other color generator, but on this Eva Design Color you can export the color schemes on SCSS format, let me show you how easy it is:

1. Export the file by choosing “Nebular Theme”

2. Put the new color schemes to your theme.scss file. You also can make your theme and declare on theme.module.ts (you can see more info on this documentation), but to make simpler we directly replace the existing theme (default theme) like this one :

// @nebular theming framework@import ‘~@nebular/theme/styles/theming’;// @nebular out of the box themes@import ‘~@nebular/theme/styles/themes’;$nb-themes: nb-register-theme((color-primary-100: #FBE0DD,
color-primary-200: #F8BCBC,
color-primary-300: #EB959D,
color-primary-400: #D87588,
color-primary-500: #BE4B6C,
color-primary-600: #A33660,
color-primary-700: #882555,
color-primary-800: #6E1749,
color-primary-900: #5B0E42,
color-primary-1000: #4E0A3E,
color-primary-1100: #41073A,
color-primary-transparent-100: rgba(190, 75, 108, 0.08),
color-primary-transparent-200: rgba(190, 75, 108, 0.16),
color-primary-transparent-300: rgba(190, 75, 108, 0.24),
color-primary-transparent-400: rgba(190, 75, 108, 0.32),
color-primary-transparent-500: rgba(190, 75, 108, 0.4),
color-primary-transparent-600: rgba(190, 75, 108, 0.48),
………….), default, default);

And your themes are already implemented!

Build a simple web app with Nebular

Here, we will make a simple “daily highlight” web app with some components from ngx-admin template so you can while learning some awesome features from Nebular. For backed integration, we will use a customizable REST endpoint by Crudcrud.com. Come on!

1. Clean unused page
You can clean unused components on folder “src”. This step will make the time of compiling on Angular become lighter. As we know that Angular always compiles all components, if the component is not much, it will be lighter and faster. If you are already familiar with Angular 8 and 9, there are two ways: compiler, JIT and AOT (you can get further information on this page).

2. Customize sidebar
For the first, don’t forget to update the routing files like this one :

import { RouterModule, Routes } from ‘@angular/router’;
import { NgModule } from ‘@angular/core’;
import { PagesComponent } from ‘./pages.component’;
import { NotFoundComponent } from ‘./miscellaneous/not-found/not-found.component’;
const routes: Routes = [{
path: ‘’,
component: PagesComponent,
children: [
{
path: ‘layout’,
loadChildren: () => import(‘./layout/layout.module’)
.then(m => m.LayoutModule),
},
{
path: ‘’,
redirectTo: ‘layout’,
pathMatch: ‘full’,
},
{
path: ‘**’,
component: NotFoundComponent,
},
],
}];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class PagesRoutingModule {
}

{your-spesific-component}routing.files.ts

import { NgModule } from ‘@angular/core’;
import { Routes, RouterModule } from ‘@angular/router’;
import { LayoutComponent } from ‘./layout.component’;
import { StepperComponent } from ‘./stepper/stepper.component’;
import { ListComponent } from ‘./list/list.component’
const routes: Routes = [{
path: ‘’,
component: LayoutComponent,
children: [
{
path: ‘stepper’,
component: StepperComponent,
},
{
path: ‘list’,
component: ListComponent,
},
{
path: ‘’,
redirectTo: ‘stepper’,
component: StepperComponent,
},
],
}];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class LayoutRoutingModule {
}

Update the pages.module file :

import { NgModule } from ‘@angular/core’;
import { NbMenuModule } from ‘@nebular/theme’;
import { ThemeModule } from ‘../@theme/theme.module’;
import { PagesComponent } from ‘./pages.component’;
import { PagesRoutingModule } from ‘./pages-routing.module’;
import { MiscellaneousModule } from ‘./miscellaneous/miscellaneous.module’;
@NgModule({
imports: [
PagesRoutingModule,
ThemeModule,
NbMenuModule,
MiscellaneousModule,
],
declarations: [
PagesComponent,
],
})
export class PagesModule {
}

Ensure the hierarchy of folder like this one:

3. Customize the sidebar
customize the sidebar on src -> pages -> pages.menu.ts like this one :

4. Customize the layout
Here, we don’t need the header, just a sidebar to show the menu list. If you are already familiar with the lifecycle of AngularJS, you can understand how components can be reusable. So here are the things, if you build some project with Angular and some components are similar and better if we separate components as small as we can so we can use it on the other page.

So we will customize the main file that will be rendering the main component when the app is run, one-column.layout.ts.

5. Create simple insert
{your-spesific-component}.component.html

<div class=”steppers-container row”>
<div class=”col-md-12 col-lg-12 col-xxxl-12">
<nb-card>
<nb-card-body>
<nb-stepper #stepper>
<nb-step [stepControl]=”secondForm”>
<form [formGroup]=”secondForm” (ngSubmit)=”onSecondSubmit(secondForm.value)” class=”step-container”>
<p class=”lorem”>
Input your highlight today!
</p>
<div class=”input-group”>
<input type=”text” placeholder=”Ex. Watching Netflix” class=”form-control” formControlName=”secondCtrl”
[ngClass]=”{‘form-control-danger’: secondForm.invalid && (secondForm.dirty || secondForm.touched)}”>
</div>
<button nbButton>Submit</button>
</form>
</nb-step>
<nb-step [stepControl]=”thirdForm” [hidden]=”true” label=”Third step”>
<div class=”step-container”>
<h3>To-do list added!</h3>
<button nbButton (click)=”stepper.reset()”>Add More</button
<button nbButton routerLink=”../list”>Go to List</button>
</div>
</nb-step>
</nb-stepper>
</nb-card-body>
</nb-card>
</div>
</div>

{your-spesific-component}.component.ts

import { Component, OnInit, ViewChild } from ‘@angular/core’;
import { FormBuilder, FormGroup, Validators } from ‘@angular/forms’;
import { NbStepperComponent } from ‘@nebular/theme’;
import { TodoService } from ‘../todolist.service’
import { ToastrService } from ‘../../../_services/toastr.service’;
@Component({
selector: ‘ngx-stepper’,
templateUrl: ‘stepper.component.html’,
styleUrls: [‘stepper.component.scss’],
})
export class StepperComponent implements OnInit {
firstForm: FormGroup;
secondForm: FormGroup;
thirdForm: FormGroup;
arrDataTodolist:any = [];
firstCtrl: any;
secondCtrl: any;
@ViewChild(‘stepper’) stepperComponent: NbStepperComponent;
constructor(
private fb: FormBuilder,
private service : TodoService,
private toast: ToastrService,) {
}
ngOnInit() {
this.firstForm = this.fb.group({
firstCtrl: [‘’, Validators.required],
});
this.secondForm = this.fb.group({
secondCtrl: [‘’, Validators.required],
});
this.thirdForm = this.fb.group({
thirdCtrl: [‘’, Validators.required],
});
}
onSecondSubmit(formData) {
this.service.addTodo(formData.secondCtrl).subscribe(
res => {
this.firstCtrl = res;
this.toast.simpleToast(‘success’,‘Seller Upgrade Successfully’,‘’,);this.stepperComponent.next();},err => {const errMessage = err.error.message? err.error.message: ‘Problem Communicating With Servers’;this.toast.simpleToast(‘danger’, errMessage, ‘’);},);this.secondForm.markAsDirty();}}

Your service

addTodo(todoDesc): Observable < Object >
{
const paramData = {
todoName: todoDesc,
isDone: 0
};
console.log(paramData);
return this.http.post(
'api/todo/',
paramData
);
}

If you get some problems with CORS when you get data from crudcrud.com, I give you the advice to fix it by using a proxy. Here is the page you can follow. In there, you just add a new configuration proxy file (proxy.conf.json) then modify the angular.json file to declare it. You also can see on GitHub, here it is.

Cause we use crudcrud.com free, therefore it serves you backend service just on 24 hours and 100 transactions. So if you get some problems when doing development about getting data, you should check your API frequently to ensure it has not expired.

6. Create list page
Generate new component for the list page

list.component.html

<nb-card>
<table class="table table-striped">
<thead>
<th class="checkbox-item-th">Todo List</th>
<th></th>
</thead>
<tr *ngFor="let item of dataList">
<td>
<nb-checkbox (checkedChange)="setTodoStat(item._id, item.todoName, $event)" [(ngModel)]="item.isDone"></nb-checkbox>
<td [ngClass]="{linethrough: item.isDone}">
{{ item.todoName }}
</td>
</tr>
</table>
</nb-card>

list.component.ts

import { Component, OnInit } from '@angular/core';
import { getMaxListeners } from 'process';
import { TodoService } from '../todolist.service';
import { ToastrService } from '../../../_services/toastr.service';

@Component({
selector: 'ngx-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.scss']
})
export class ListComponent implements OnInit {
dataList: any;
todoStat: any;
todoDone: boolean;
idSelected: any;

constructor(
private service : TodoService,
private toast: ToastrService
) { }

ngOnInit() {
this.getTodoList();
}

getTodoList(){
this.service.GetList().subscribe(
res => {
this.dataList = res;
},
err => {
const errMessage = err.error.message
? err.error.message
: 'Problem Communicating With Servers';
this.toast.simpleToast('danger', errMessage, '');
},
);
}

setTodoStat(id,todoName,event){
this.todoStat = 0;
if(event == true){
this.todoStat = 1;
}
this.service.setTodoStat(id,todoName,this.todoStat)
.subscribe(res =>
{
console.log("sukseuor");
window.location.reload();
},
err => {
const errMessage = err.error.message
? err.error.message
: 'Problem Communicating With Servers';
this.toast.simpleToast('danger', errMessage, '');
});
}
}

Service

GetList(): Observable<Object> {
return this.http.get(
'api/todo/'
);
}

setTodoStat(id, todoDesc, isActive): Observable<Object> {
const paramData = {
todoName: todoDesc,
isDone: isActive
};
return this.http.put(
'api/todo/' + id,
paramData
);
}

We are done for part 1, you also can see full code on Github :)

--

--

Glovory Tech

We are a comprehensive digital product agency specializing in UI/UX design & development of websites and mobile applications, IoT, AI, and custom software dev.