Top
<button type="button" class="btn btn-primary">Primary Button</button>
<button type="button" class="btn btn-secondary">Secondary Button</button>
<button type="button" class="btn btn-success">Success Button</button>
<button type="button" class="btn btn-info">Info Button</button>
<button type="button" class="btn btn-warning">Warning Button</button>
<button type="button" class="btn btn-danger">Danger Button</button>
<button type="button" class="btn btn-light">Light Button</button>
To use another types button you have to link the related css file according to types of buttons in a head tag
<span class="badge badge-primary">Primary</span>
<span class="badge badge-secondary">Secondary</span>
<span class="badge badge-success">Success</span>
<span class="badge badge-info">Info</span>
<span class="badge badge-warning text-dark">Warning</span>
<span class="badge badge-danger">Danger</span>
<span class="badge badge-light text-dark">Light</span>
<span class="badge badge-dark">Dark</span>
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
<div class="progress-bar bg-primary" role="progressbar" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
<div class="progress-bar bg-secondary" role="progressbar" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
<div class="progress-bar bg-success" role="progressbar" style="width: 75%" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
<div class="progress-bar bg-info" role="progressbar" style="width: 100%" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100">
</div>
<div class="alert alert-primary" role="alert">This is a info alert—check it out!</div>
<div class="alert alert-secondary" role="alert">This is a light alert—check it out!</div>
<div class="alert alert-success" role="alert">This is a success alert—check it out!</div>
<div class="alert alert-info" role="alert">This is a danger alert—check it out!</div>
<div class="alert alert-warning" role="alert">This is a secondary alert—check it out!</div>
<div class="alert alert-danger" role="alert">This is a warning alert—check it out!</div>
<div class="alert alert-light" role="alert">This is a dark alert—check it out!</div>
<div class="alert alert-dark" role="alert">This is a dark alert—check it out!</div>
<button type="button" class="btn btn-outline-primary" placement="top"
ngbPopover="Vivamus sagittis lacus vel augue laoreet rutrum faucibus." popoverTitle="Popover on top">
Popover on top
</button>
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { NgbPopoverConfig, NgbPopover } from '@ng-bootstrap/ng-bootstrap';
import { DatePipe } from '@angular/common';
@Component({
selector: 'app-popover',
templateUrl: './popover.html',
styleUrls: ['./popover.scss'],
providers: [NgbPopoverConfig],
standalone: true,
imports: [NgbPopover, DatePipe]
})
export class Popover implements OnInit {
}
<button type="button" class="btn btn-outline-primary me-2" placement="top" ngbTooltip="Tooltip on top">
Tooltip on top
</button>
import { Component } from '@angular/core';
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-tooltip',
templateUrl: './tooltip.html',
styleUrls: ['./tooltip.scss'],
standalone: true,
imports: [NgbTooltip],
})
export class Tooltip{
}
<div ngbDropdown class="d-inline-block" placement="bottom">
<button class="btn btn-outline-primary" id="dropdownBasic1" ngbDropdownToggle >Toggle dropdown</button>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<button class="dropdown-item">Action - 1</button>
<button class="dropdown-item">Another Action</button>
<button class="dropdown-item">Something else is here</button>
</div>
</div>
import { Component } from '@angular/core';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'ngbd-dropdown-basic',
standalone: true,
imports: [NgbDropdownModule],
templateUrl: './dropdown-basic.html',
})
export class NgbdDropdownBasic {}
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting,remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting,remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav-tabs">
<li [ngbNavItem]="1">
<button ngbNavLink>One</button>
<ng-template ngbNavContent>
<p>
Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth
master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro
keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat
salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.
</p>
</ng-template>
</li>
<li [ngbNavItem]="2">
<button ngbNavLink>Two</button>
<ng-template ngbNavContent>
<p>
Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko
farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts
ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar
helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson
8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester
stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.
</p>
</ng-template>
</li>
<li [ngbNavItem]="3">
<button ngbNavLink>Three</button>
<ng-template ngbNavContent>
<p>
Sed commodo, leo at suscipit dictum, quam est porttitor sapien, eget sodales nibh elit id diam. Nulla facilisi.
Donec egestas ligula vitae odio interdum aliquet. Duis lectus turpis, luctus eget tincidunt eu, congue et odio.
Duis pharetra et nisl at faucibus. Quisque luctus pulvinar arcu, et molestie lectus ultrices et. Sed diam urna,
egestas ut ipsum vel, volutpat volutpat neque. Praesent fringilla tortor arcu. Vivamus faucibus nisl enim, nec
tristique ipsum euismod facilisis. Morbi ut bibendum est, eu tincidunt odio. Orci varius natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Mauris aliquet odio ac lorem aliquet ultricies in eget
neque. Phasellus nec tortor vel tellus pulvinar feugiat.
</p>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="nav" class="mt-2"></div>
import { Component } from '@angular/core';
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'ngbd-nav-basic',
standalone: true,
imports: [NgbNavModule],
templateUrl: './nav-basic.html',
})
export class NgbdNavBasic {
active = 1;
}
<div class="card">
<div ngbAccordion>
<div ngbAccordionItem [collapsed]="false">
<h2 ngbAccordionHeader>
<button ngbAccordionButton>Simple</button>
</h2>
<div ngbAccordionCollapse>
<div ngbAccordionBody>
<ng-template>
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon
officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf
moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim
keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur
butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably
haven't heard of them accusamus labore sustainable VHS.
</ng-template>
</div>
</div>
</div>
<div ngbAccordionItem>
<h2 ngbAccordionHeader>
<button ngbAccordionButton>
<span>★ <b>Fancy</b> title ★</span>
</button>
</h2>
<div ngbAccordionCollapse>
<div ngbAccordionBody>
<ng-template>
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon
officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf
moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim
keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur
butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably
haven't heard of them accusamus labore sustainable VHS.
</ng-template>
</div>
</div>
</div>
<div ngbAccordionItem [disabled]="true">
<h2 ngbAccordionHeader>
<button ngbAccordionButton>Disabled</button>
</h2>
<div ngbAccordionCollapse>
<div ngbAccordionBody>
<ng-template>
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon
officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf
moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim
keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur
butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably
haven't heard of them accusamus labore sustainable VHS.
</ng-template>
</div>
</div>
</div>
</div>
import { Component } from '@angular/core';
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'ngbd-accordion-basic',
standalone: true,
imports: [NgbAccordionModule],
templateUrl: './accordion-basic.html',
})
export class NgbdAccordionBasic {}
Installing and usage
npm install @ng-bootstrap/ng-bootstrap
@if (images) {
<ngb-carousel>
<ng-template ngbSlide>
<div class="picsum-img-wrapper">
<img [src]="images[0]" alt="Random first slide" />
</div>
<div class="carousel-caption">
<h3>First slide label</h3>
<p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>
</div>
</ng-template>
<ng-template ngbSlide>
<div class="picsum-img-wrapper">
<img [src]="images[1]" alt="Random second slide" />
</div>
<div class="carousel-caption">
<h3>Second slide label</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</ng-template>
<ng-template ngbSlide>
<div class="picsum-img-wrapper">
<img [src]="images[2]" alt="Random third slide" />
</div>
<div class="carousel-caption">
<h3>Third slide label</h3>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p>
</div>
</ng-template>
</ngb-carousel>
}
import { Component } from '@angular/core';
import { NgbCarouselModule } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'ngbd-carousel-basic',
standalone: true,
imports: [NgbCarouselModule],
templateUrl: './carousel-basic.html',
})
export class NgbdCarouselBasic {
images = [944, 1011, 984].map((n) => `https://picsum.photos/id/${n}/900/500`);
}
Installing and usage
npm install @ng-bootstrap/ng-bootstrap
<ngb-rating [(rate)]="rating" />
<hr /><pre>Rate: <b>{{ rating }}</b></pre>
import { Component } from '@angular/core';
import { NgbRatingModule } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'ngbd-rating-basic',
standalone: true,
imports: [NgbRatingModule],
templateUrl: './rating-basic.html',
})
export class NgbdRatingBasic {
rating = 8;
}
Installing and usage
npm i sweetalert2
<button class="btn btn-primary sweet-1" type="button" (click)="basicAlert()">Basic</button>
// ES6 Modules or TypeScript
import { Component } from '@angular/core';
import Swal from 'sweetalert2';
@Component({
selector: 'app-sweet-alert2',
templateUrl: './sweet-alert2.html',
styleUrls: ['./sweet-alert2.scss'],
standalone: true
})
export class SweetAlert2 {
// Basic Alert
basicAlert() {
Swal.fire('Hello world!');
}
}
Installing and usage
npm i @angular-slider/ngx-slider
<ngx-slider [(value)]="value" [options]="options"></ngx-slider>
import { NgxSliderModule, Options } from '@angular-slider/ngx-slider';
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-range-slider',
templateUrl: './range-slider.html',
styleUrls: ['./range-slider.scss'],
standalone: true,
imports: [FormsModule, NgxSliderModule]
})
export class RangeSlider {
public value: number = 550;
options: Options = {
floor: 100,
ceil: 1000
}
}
Installing and usage
npm i ngx-dropzone-wrapper
<dropzone [config]="configSingle" [classList]="'custom-dropzone'" [message]="textSignle"
></dropzone>
import { Component} from '@angular/core';
import { DropzoneConfigInterface, DropzoneModule } from 'ngx-dropzone-wrapper';
@Component({
selector: 'app-dropzone',
templateUrl: './dropzone.html',
styleUrls: ['./dropzone.scss'],
standalone: true,
imports: [DropzoneModule]
})
export class Dropzone {
public configSingle: DropzoneConfigInterface = {
clickable: true,
url: 'https://httpbin.org/post',
acceptedFiles: 'image/*',
addRemoveLinks: true,
uploadMultiple: false,
maxFiles: 1,
};
public textSignle = 'Drop files here or click to upload.
(This is just a demo dropzone. Selected files are not actually uploaded.)'
}
Installing and usage
npm install @ng-bootstrap/ng-bootstrap
<ngb-datepicker #dp [(ngModel)]="model" (navigate)="date = $event.next">
</ngb-datepicker>
<hr />
<div class="btn-showcase">
<button class="btn btn-sm btn-outline-primary me-2" (click)="selectToday()">Select Today</button>
<button class="btn btn-sm btn-outline-primary me-2" (click)="dp.navigateTo()">To current month</button>
<button class="btn btn-sm btn-outline-primary me-2" (click)="dp.navigateTo({year: 2013, month: 2})">To Feb
2013</button>
</div>
<hr />
<span class="d-block">Month: {{ date.month }}.{{ date.year }}</span>
<span class="d-block">Model: {{ model | json }}</span>
import { JsonPipe } from '@angular/common';
import { Component, inject, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NgbCalendar, NgbDate, NgbDatepicker, NgbDatepickerModule, NgbDateStruct, NgbInputDatepicker } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-datepicker',
templateUrl: './datepicker.html',
styleUrls: ['./datepicker.scss'],
standalone: true,
imports: [NgbDatepicker, FormsModule, NgbInputDatepicker, JsonPipe,NgbDatepickerModule, FormsModule]
})
export class Datepicker {
model: NgbDateStruct;
date: { year: number, month: number };
}
Installing and usage
npm i @ng-select/ng-select
<ng-select [items]="defaultBindingsList" placeholder="Select" class="js-example-placeholder-multiple"
[(ngModel)]="selectedCity"></ng-select>
import { TitleCasePipe } from '@angular/common';
import { Component} from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
@Component({
selector: 'app-select2',
templateUrl: './select2.html',
styleUrls: ['./select2.scss'],
standalone: true,
imports: [NgSelectModule, FormsModule, TitleCasePipe]
})
export class Select2 {
public defaultBindingsList = [
{ value: "1", label: "Alabama", job: "Developer" },
{ value: "2", label: "Wyoming", job: "Developer" },
{ value: "3", label: "Coming", job: "Designer",disabled:true },
{ value: "4", label: "Hanry Die", job: "Designer" },
{ value: "5", label: "John Doe", job: "Designer" },
];
public selectedCity: string;
}
Installing and usage
npm install @ng-bootstrap/ng-bootstrap
<label for="typeahead-basic">Search for a state:</label>
<input id="typeahead-basic" type="text" class="form-control" [(ngModel)]="model" [ngbTypeahead]="search" />
import {Component} from '@angular/core';
import { Component } from '@angular/core';
import { NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
import { Observable, OperatorFunction } from 'rxjs';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
import { FormsModule } from '@angular/forms';
import { JsonPipe } from '@angular/common';
const states = [
'Alabama',
'Alaska',
'American Samoa',
'Arizona',
'Arkansas',
'California',
'Colorado',
'Connecticut',
'Delaware',
'District Of Columbia',
'Federated States Of Micronesia',
'Florida',
'Georgia',
'Guam',
'Hawaii',
'Idaho',
'Illinois',
'Indiana',
'Iowa',
'Kansas',
'Kentucky',
'Louisiana',
'Maine',
'Marshall Islands',
'Maryland',
'Massachusetts',
'Michigan',
'Minnesota',
'Mississippi',
'Missouri',
'Montana',
'Nebraska',
'Nevada',
'New Hampshire',
'New Jersey',
'New Mexico',
'New York',
'North Carolina',
'North Dakota',
'Northern Mariana Islands',
'Ohio',
'Oklahoma',
'Oregon',
'Palau',
'Pennsylvania',
'Puerto Rico',
'Rhode Island',
'South Carolina',
'South Dakota',
'Tennessee',
'Texas',
'Utah',
'Vermont',
'Virgin Islands',
'Virginia',
'Washington',
'West Virginia',
'Wisconsin',
'Wyoming',
];
@Component({
selector: 'ngbd-typeahead-basic',
standalone: true,
imports: [NgbTypeaheadModule, FormsModule, JsonPipe],
templateUrl: './typeahead-basic.html',
styles: `.form-control { width: 300px; }`,
})
export class NgbdTypeaheadBasic {
model:sting;
search: OperatorFunction = (text$: Observable) =>
text$.pipe(
debounceTime(200),
distinctUntilChanged(),
map((term) =>
term.length < 2 ? [] : states.filter((v) => v.toLowerCase().indexOf(term.toLowerCase()) > -1).slice(0, 10),
),
);
}
Installing and usage
npm install @ng-bootstrap/ng-bootstrap
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Country</th>
<th scope="col">Area</th>
<th scope="col">Population</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let country of countries; index as i">
<th scope="row">{{ i + 1 }}</th>
<td>
<img [src]="'https://upload.wikimedia.org/wikipedia/commons/' + country.flag" class="mr-2" style="width: 20px">
{{ country.name }}
</td>
<td>{{ country.area | number }}</td>
<td>{{ country.population | number }}</td>
</tr>
</tbody>
</table>
import { Component } from '@angular/core';
interface Country {
name: string;
flag: string;
area: number;
population: number;
}
const COUNTRIES: Country[] = [
{
name: 'Russia',
flag: 'f/f3/Flag_of_Russia.svg',
area: 17075200,
population: 146989754
},
{
name: 'Canada',
flag: 'c/cf/Flag_of_Canada.svg',
area: 9976140,
population: 36624199
},
{
name: 'United States',
flag: 'a/a4/Flag_of_the_United_States.svg',
area: 9629091,
population: 324459463
},
{
name: 'China',
flag: 'f/fa/Flag_of_the_People%27s_Republic_of_China.svg',
area: 9596960,
population: 1409517397
}
];
@Component({
selector: 'ngbd-table-basic',
templateUrl: './table-basic.html'
})
export class NgbdTableBasic {
countries = COUNTRIES;
}
Installing and usage
npm i @ng-bootstrap/ng-bootstrap
// table.html
<form>
<div class="mb-3 row">
<label for="table-complete-search" class="col-xs-3 col-sm-auto col-form-label">Full text search:</label>
<div class="col-xs-3 col-sm-auto">
<input
id="table-complete-search"
type="text"
class="form-control"
name="searchTerm"
[(ngModel)]="service.searchTerm"
/>
</div>
@if (service.loading$ | async) {
<span class="col col-form-label">Loading...</span>
}
</div>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col" sortable="name" (sort)="onSort($event)">Country</th>
<th scope="col" sortable="area" (sort)="onSort($event)">Area</th>
<th scope="col" sortable="population" (sort)="onSort($event)">Population</th>
</tr>
</thead>
<tbody>
@for (country of countries$ | async; track country.id) {
<tr>
<th scope="row">{{ country.id }}</th>
<td>
<img
[src]="'https://upload.wikimedia.org/wikipedia/commons/' + country.flag"
[alt]="'The flag of ' + country.name"
class="me-2"
style="width: 20px"
/>
<ngb-highlight [result]="country.name" [term]="service.searchTerm" />
</td>
<td><ngb-highlight [result]="country.area | number" [term]="service.searchTerm" /></td>
<td><ngb-highlight [result]="country.population | number" [term]="service.searchTerm" /></td>
</tr>
} @empty {
<tr>
<td colspan="4" style="text-align: center">No countries found</td>
</tr>
}
</tbody>
</table>
<div class="d-flex justify-content-between p-2">
<ngb-pagination [collectionSize]="(total$ | async)!" [(page)]="service.page" [pageSize]="service.pageSize">
</ngb-pagination>
<select class="form-select" style="width: auto" name="pageSize" [(ngModel)]="service.pageSize">
<option [ngValue]="2">2 items per page</option>
<option [ngValue]="4">4 items per page</option>
<option [ngValue]="6">6 items per page</option>
</select>
</div>
</form>
// table.ts
import { AsyncPipe, DecimalPipe } from '@angular/common';
import { Component, QueryList, ViewChildren } from '@angular/core';
import { Observable } from 'rxjs';
import { Country } from './country';
import { CountryService } from './country.service';
import { NgbdSortableHeaderDirective, SortEvent } from './sortable.directive';
import { FormsModule } from '@angular/forms';
import { NgbHighlight, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'ngbd-table-complete',
standalone: true,
imports: [DecimalPipe, FormsModule, AsyncPipe, NgbHighlight, NgbdSortableHeader, NgbPaginationModule],
templateUrl: './table-complete.html',
providers: [CountryService, DecimalPipe],
})
export class NgbdTableComplete {
public service = inject(CountryService);
public countries$: Observable = this.service.countries$;
public total$: Observable = this.service.total$;
readonly headers = viewChildren(NgbdSortableHeaderDirective);
onSort({ column, direction }: SortEvent) {
this.headers().forEach(header => {
if (header.sortable() !== column) {
header.currentDirection.set('');
}
});
this.service.sortColumn = column;
this.service.sortDirection = direction;
}
}
// table service
import { Injectable, PipeTransform } from '@angular/core';
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
import { Country } from './country';
import { COUNTRIES } from './countries';
import { DecimalPipe } from '@angular/common';
import { debounceTime, delay, switchMap, tap } from 'rxjs/operators';
import { SortColumn, SortDirection } from './sortable.directive';
interface SearchResult {
countries: Country[];
total: number;
}
interface State {
page: number;
pageSize: number;
searchTerm: string;
sortColumn: SortColumn;
sortDirection: SortDirection;
}
const compare = (v1: string | number, v2: string | number) => (v1 < v2 ? -1 : v1 > v2 ? 1 : 0);
function sort(countries: Country[], column: SortColumn, direction: string): Country[] {
if (direction === '' || column === '') {
return countries;
} else {
return [...countries].sort((a, b) => {
const res = compare(a[column], b[column]);
return direction === 'asc' ? res : -res;
});
}
}
function matches(country: Country, term: string, pipe: PipeTransform) {
return (
country.name.toLowerCase().includes(term.toLowerCase()) ||
pipe.transform(country.area).includes(term) ||
pipe.transform(country.population).includes(term)
);
}
@Injectable({ providedIn: 'root' })
export class CountryService {
public pipe = inject(DecimalPipe);
private _loading$ = new BehaviorSubject(true);
private _search$ = new Subject();
private _countries$ = new BehaviorSubject([]);
private _total$ = new BehaviorSubject(0);
private _state: State = {
page: 1,
pageSize: 4,
searchTerm: '',
sortColumn: '',
sortDirection: '',
};
constructor() {
this._search$
.pipe(
tap(() => this._loading$.next(true)),
debounceTime(200),
switchMap(() => this._search()),
delay(200),
tap(() => this._loading$.next(false)),
)
.subscribe((result) => {
this._countries$.next(result.countries);
this._total$.next(result.total);
});
this._search$.next();
}
get countries$() {
return this._countries$.asObservable();
}
get total$() {
return this._total$.asObservable();
}
get loading$() {
return this._loading$.asObservable();
}
get page() {
return this._state.page;
}
get pageSize() {
return this._state.pageSize;
}
get searchTerm() {
return this._state.searchTerm;
}
set page(page: number) {
this._set({ page });
}
set pageSize(pageSize: number) {
this._set({ pageSize });
}
set searchTerm(searchTerm: string) {
this._set({ searchTerm });
}
set sortColumn(sortColumn: SortColumn) {
this._set({ sortColumn });
}
set sortDirection(sortDirection: SortDirection) {
this._set({ sortDirection });
}
private _set(patch: Partial) {
Object.assign(this._state, patch);
this._search$.next();
}
private _search(): Observable {
const { sortColumn, sortDirection, pageSize, page, searchTerm } = this._state;
// 1. sort
let countries = sort(COUNTRIES, sortColumn, sortDirection);
// 2. filter
countries = countries.filter((country) => matches(country, searchTerm, this.pipe));
const total = countries.length;
// 3. paginate
countries = countries.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
return of({ countries, total });
}
}
// directives
import { Directive, input, output, signal, HostBinding, HostListener } from '@angular/core';
import { Country } from '../data/tables';
export type SortColumn = keyof Country | '';
export type SortDirection = 'asc' | 'desc' | '';
const rotate: { [key: string]: SortDirection } = { asc: 'desc', desc: '', '': 'asc' };
export interface SortEvent {
column: SortColumn;
direction: SortDirection;
}
@Directive({
selector: 'th[sortable]',
standalone: true,
})
export class NgbdSortableHeaderDirective {
// Input signals
readonly sortable = input(''); // Column name
readonly direction = input(''); // Initial direction
// Local writable signal
public currentDirection = signal(this.direction());
// Output event
readonly sort = output();
// HostBinding for CSS classes
@HostBinding('class.asc')
get isAsc() {
return this.currentDirection() === 'asc';
}
@HostBinding('class.desc')
get isDesc() {
return this.currentDirection() === 'desc';
}
// Handle click
@HostListener('click')
rotate() {
this.currentDirection.set(rotate[this.currentDirection()]);
this.sort.emit({ column: this.sortable(), direction: this.currentDirection() });
}
}
// data
export interface Country {
id: number;
name: string;
flag: string;
area: number;
population: number;
}
export const COUNTRIES: Country[] = [
{
id: 1,
name: 'Russia',
flag: 'f/f3/Flag_of_Russia.svg',
area: 17075200,
population: 146989754,
},
{
id: 2,
name: 'France',
flag: 'c/c3/Flag_of_France.svg',
area: 640679,
population: 64979548,
},
{
id: 3,
name: 'Germany',
flag: 'b/ba/Flag_of_Germany.svg',
area: 357114,
population: 82114224,
},
{
id: 4,
name: 'Portugal',
flag: '5/5c/Flag_of_Portugal.svg',
area: 92090,
population: 10329506,
},
{
id: 5,
name: 'Canada',
flag: 'c/cf/Flag_of_Canada.svg',
area: 9976140,
population: 36624199,
},
{
id: 6,
name: 'Vietnam',
flag: '2/21/Flag_of_Vietnam.svg',
area: 331212,
population: 95540800,
},
{
id: 7,
name: 'Brazil',
flag: '0/05/Flag_of_Brazil.svg',
area: 8515767,
population: 209288278,
},
{
id: 8,
name: 'Mexico',
flag: 'f/fc/Flag_of_Mexico.svg',
area: 1964375,
population: 129163276,
},
{
id: 9,
name: 'United States',
flag: 'a/a4/Flag_of_the_United_States.svg',
area: 9629091,
population: 324459463,
},
{
id: 10,
name: 'India',
flag: '4/41/Flag_of_India.svg',
area: 3287263,
population: 1324171354,
},
{
id: 11,
name: 'Indonesia',
flag: '9/9f/Flag_of_Indonesia.svg',
area: 1910931,
population: 263991379,
},
{
id: 12,
name: 'Tuvalu',
flag: '3/38/Flag_of_Tuvalu.svg',
area: 26,
population: 11097,
},
{
id: 13,
name: 'China',
flag: 'f/fa/Flag_of_the_People%27s_Republic_of_China.svg',
area: 9596960,
population: 1409517397,
},
];
Installing and usage
npm i ng2-google-charts
<google-chart [data]="pieChart1"></google-chart>
import { Component } from '@angular/core';
import * as chartData from '../../../shared/data/chart/google-chart';
import { Ng2GoogleChartsModule } from 'ng2-google-charts';
@Component({
selector: 'app-google',
templateUrl: './google.html',
styleUrls: ['./google.scss'],
standalone: true,
imports: [Ng2GoogleChartsModule]
})
export class Google {
constructor() { }
// Pie Chart
public pieChart1 = chartData.pieChart1
}
let primary_color = localStorage.getItem('primary_color') || '#7e37d8';
let secondary_color = localStorage.getItem('secondary_color') || '#fe80b2';
// Pie Chart 1
export var pieChart1 = {
chartType: 'PieChart',
dataTable: [
['Task', 'Hours per Day'],
['Work', 5],
['Eat', 10],
['Commute', 15],
['Watch TV', 20],
['Sleep', 25]
],
options: {
title: 'My Daily Activities',
width: '100%',
height: 400,
colors: ["#06b5dd", primary_color, secondary_color, "#80cf00", "#FF5370"],
backgroundColor: 'transparent'
},
};
Installing and usage
npm i ng2-charts
<canvas baseChart class="chart"
baseChart
class="chart"
[data]="barChart"
[datasets]="barChart.datasets"
[options]="barChart.barOptions">
</canvas>
import { Component } from '@angular/core';
import { BarController, BarElement, CategoryScale, LinearScale } from 'chart.js';
import { BaseChartDirective, provideCharts } from 'ng2-charts';
import { barChart } from '../../../../shared/data/charts/chartsjs';
@Component({
selector: 'app-bars-chart',
templateUrl: './bars-chart.html',
styleUrls: ['./bars-chart.scss'],
imports: [BaseChartDirective],
providers: [
provideCharts({
registerables: [BarController, CategoryScale, LinearScale, BarElement],
}),
],
})
export class BarsChart {
public barChart = barChart;
}
let primary_color = localStorage.getItem('primary_color') || 'var(--theme-default)';
let secondary_color = localStorage.getItem('secondary_color') || 'var(--theme-secondary)';
let primary_color = '#2B5F60';
let secondary_color = '#C06240';
export const barChart = {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
responsive: false,
datasets: [
{
label: 'My First dataset',
backgroundColor: 'rgba(43, 94, 94, 0.4)',
borderColor: primary_color,
borderWidth: 2,
data: [35, 59, 80, 81, 56, 55, 40],
},
{
label: 'My Second dataset',
borderColor: secondary_color,
backgroundColor: 'rgba(192, 98, 64, 0.4)',
borderWidth: 2,
data: [28, 48, 40, 19, 86, 27, 90],
},
],
barOptions: [
{
scaleBeginAtZero: true,
scaleShowGridLines: true,
scaleGridLineColor: 'rgba(0,0,0,0.1)',
scaleGridLineWidth: 1,
scaleShowHorizontalLines: true,
scaleShowVerticalLines: true,
barShowStroke: true,
barStrokeWidth: 2,
barValueSpacing: 5,
barDatasetSpacing: 1,
},
],
};
app.config.ts
import { HttpClient } from '@angular/common/http';
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideRouter } from '@angular/router';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { provideCharts, withDefaultRegisterables } from 'ng2-charts';
import { routes } from './app.routes';
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideAnimations(),
provideCharts(withDefaultRegisterables()),
]
};
Installing and usage
npm i ng-chartist
<x-chartist [configuration]="chart1"></x-chartist>
// bar-chart.ts
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import * as chartData from '../../../shared/data/chart/chartist';
import { ChartistModule } from 'ng-chartist';
@Component({
selector: 'app-chartist',
templateUrl: './chartist.html',
styleUrls: ['./chartist.scss'],
standalone: true,
imports: [ChartistModule]
})
export class Chartist {
constructor() { }
// Charts
public chart1 = chartData.chart1;
}
// bar-chart.ts
import * as Chartist from 'chartist';
import { BarChartConfiguration, LineChartConfiguration, PieChartConfiguration } from 'ng-chartist
let primary_color = localStorage.getItem('primary_color') || '#2B5F60';
let secondary_color = localStorage.getItem('secondary_color') || '#C06240';
export var chart1: LineChartConfiguration = {
type: 'Line',
data: {
labels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
series: [
[12, 9, 7, 8, 5, 4, 6, 2, 3, 3, 4, 6],
[4, 5, 3, 7, 3, 5, 5, 3, 4, 4, 5, 5],
[5, 3, 4, 5, 6, 3, 3, 4, 5, 6, 3, 4],
[3, 4, 5, 6, 7, 6, 4, 5, 6, 7, 6, 3],
],
},
options: {
low: 0,
showArea: false,
fullWidth: true,
height: 250,
},
};
Installing and usage
npm i @swimlane/ngx-charts
<ngx-charts-bar-vertical [results]="barChartsingle"
[gradient]="barChartGradient" [xAxis]="barChartShowXAxis" [yAxis]="barChartShowYAxis"
[legend]="barChartShowLegend" [showXAxisLabel]="barChartShowXAxisLabel"
[showYAxisLabel]="barChartShowYAxisLabel" [xAxisLabel]="barChartXAxisLabel"
[yAxisLabel]="barChartYAxisLabel" [roundEdges]="false"">
</ngx-charts-bar-vertical>
import { Component} from '@angular/core';
import { barChartSingle, pieChart, multiData, single } from '../../../shared/data/chart/ngx-chart';
import * as graphoptions from '../../../shared/data/chart/config';
import { BarChartModule, PieChartModule, LineChartModule, AreaChartModule, NumberCardModule } from '@swimlane/ngx-charts';
@Component({
selector: 'app-ngx-chart',
templateUrl: './ngx-chart.html',
styleUrls: ['./ngx-chart.scss'],
standalone: true,
imports: [BarChartModule, PieChartModule, LineChartModule, AreaChartModule, NumberCardModule]
})
export class NgxChart {
public barChartsingle = barChartSingle;
public barChartGradient = graphoptions.barChartGradient;
public barChartShowXAxis = graphoptions.barChartShowXAxis;
public barChartShowYAxis = graphoptions.barChartShowYAxis;
public barChartShowLegend = graphoptions.barChartShowLegend;
public barChartShowXAxisLabel = graphoptions.barChartShowXAxisLabel;
public barChartXAxisLabel = graphoptions.barChartXAxisLabel;
public barChartShowYAxisLabel = graphoptions.barChartShowYAxisLabel;
public barChartYAxisLabel = graphoptions.barChartYAxisLabel;
}
// data
export var barChartSingle = [
{
"name": "Germany",
"value": 894
},
{
"name": "USA",
"value": 500
},
{
"name": "France",
"value": 720
},
{
"name": "Australia",
"value": 650
}
];
export var barChartGradient = true;
export var barChartShowXAxis = true;
export var barChartShowYAxis = true;
export var barChartShowLegend = false;
export var barChartShowXAxisLabel = true;
export var barChartXAxisLabel = 'Country';
export var barChartShowYAxisLabel = true;
export var barChartYAxisLabel = 'Population';
Installing and usage
npm i ng-apexcharts
<apx-chart [series]="splineArea2.series"
[chart]="splineArea2.chart"
[xaxis]="splineArea2.xaxis"
[stroke]="splineArea2.stroke"
[dataLabels]="splineArea2.dataLabels"
[yaxis]="splineArea2.yaxis"
[labels]="splineArea2.labels"
[legend]="splineArea2.legend"
[colors]="splineArea2.colors"></apx-chart>
import { Component, ViewChild } from "@angular/core";
import { Component } from '@angular/core';
import { NgApexchartsModule } from 'ng-apexcharts';
import * as chartData from './../../../shared/data/chart/apex';
@Component({
selector: 'app-apex-chart',
templateUrl: './apex-chart.html',
styleUrls: ['./apex-chart.scss'],
imports: [NgApexchartsModule],
})
export class ApexChart {
public splineArea1 = chartData.splineArea1;
}
// chart data //
import {BarChart} from '../../interface/charts/apex-charts';
let primary_color = localStorage.getItem('primary_color') || '#7e37d8';
let secondary_color = localStorage.getItem('secondary_color') || '#fe80b2';
export let splineArea1: BasicChart = {
series: [
{
name: 'series1',
data: [31, 40, 28, 51, 42, 109, 100],
},
{
name: 'series2',
data: [11, 32, 45, 32, 34, 52, 41],
},
],
colors: [primary_color, secondary_color],
chart: {
height: 350,
type: 'area',
toolbar: {
show: false,
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: 'smooth',
},
xaxis: {
type: 'datetime',
categories: [
'2021-09-19T00:00:00.000Z',
'2021-09-19T01:30:00.000Z',
'2021-09-19T02:30:00.000Z',
'2021-09-19T03:30:00.000Z',
'2021-09-19T04:30:00.000Z',
'2021-09-19T05:30:00.000Z',
'2021-09-19T06:30:00.000Z',
],
},
tooltip: {
x: {
format: 'dd/MM/yy HH:mm',
},
},
};
Installing and usage
npm i @angular/google-maps
<google-map width="100%" height="450px" [zoom]="zoom">
@for (marker of markers; track marker) {
<map-marker [position]="marker.position" [label]="marker.label">
</map-marker>
}
</google-map>
import { Component, AfterViewInit, viewChild } from '@angular/core';
import { GoogleMap, GoogleMapsModule } from '@angular/google-maps';
// Strong typing for markers
interface MapMarker {
position: google.maps.LatLngLiteral;
label: google.maps.MarkerLabel;
options: google.maps.MarkerOptions;
title: string;
}
@Component({
selector: 'app-map-js',
templateUrl: './map-js.html',
styleUrls: ['./map-js.scss'],
imports: [GoogleMapsModule],
standalone: true, // required if no NgModule
})
export class MapJs implements AfterViewInit {
public markers: MapMarker[] = [];
public zoom = 4;
// Google Map reference (new Angular signal-style viewChild)
readonly map = viewChild.required(GoogleMap);
ngOnInit() {
this.markers.push({
position: { lat: 40.4168, lng: -3.7038 },
label: { color: 'black', text: 'Madrid' },
options: {
draggable: true,
animation: google.maps.Animation.DROP,
},
title: 'Madrid',
});
this.markers.push({
position: { lat: 40.4168, lng: -3.7038 },
label: { color: 'black', text: 'Madrid' },
options: { draggable: true, animation: google.maps.Animation.DROP },
title: 'Madrid',
});
}
ngAfterViewInit() {
const mapInstance = this.map().googleMap;
if (mapInstance) {
const streetView = mapInstance.getStreetView();
streetView.setOptions({
position: { lat: 38.9938386, lng: -77.2515373 },
pov: { heading: 70, pitch: -10 },
});
streetView.setVisible(true);
}
}
}
Installing and usage
npm i @asymmetrik/ngx-leaflet
<div class="map-height" leaflet [leafletOptions]="options1"></div>
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { LeafletModule } from '@bluehalo/ngx-leaflet';
import * as L from 'leaflet';
@Component({
selector: 'app-leaflet-map',
templateUrl: './leaflet-map.html',
styleUrls: ['./leaflet-map.scss'],
imports: [CommonModule, LeafletModule],
})
export class LeafletMap {
options1 = {
layers: [
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '...',
}),
],
zoom: 5,
center: L.latLng(46.879966, -121.726909),
};
//Second map
layersControl = {
baseLayers: {
'Open Street Map': L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '...',
}),
'Open Cycle Map': L.tileLayer('http://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '...',
}),
},
overlays: {
'Big Circle': L.circle([46.95, -122], { radius: 5000 }),
'Big Square': L.polygon([
[46.8, -121.55],
[46.9, -121.55],
[46.9, -121.7],
[46.8, -121.7],
]),
},
};
options2 = {
layers: [
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 50,
attribution: '...',
}),
],
zoom: 5,
center: L.latLng(46.879966, -121.726909),
};
//Third map
map: L.Map;
options3 = {
layers: [
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '',
}),
],
zoom: 7,
center: L.latLng(47.482023, -1),
};
//Forth map
map4: L.Map;
homeCoords = {
lat: 23.810331,
lon: 90.412521,
};
popupText = 'Some popup text';
markerIcon = {
icon: L.icon({
iconSize: [25, 41],
iconAnchor: [10, 41],
popupAnchor: [2, -40],
iconUrl: 'assets/images/marker-icon.png',
shadowUrl: 'assets/images/marker-shadow.png',
}),
};
options4 = {
layers: [
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '',
}),
],
zoom: 5,
center: L.latLng(this.homeCoords.lat, this.homeCoords.lon),
};
initMarkers() {
const popupInfo = `${this.popupText}`;
L.marker([this.homeCoords.lat, this.homeCoords.lon], this.markerIcon)
.addTo(this.map4)
.bindPopup(popupInfo);
}
onMapReady4(map: L.Map) {
this.map4 = map;
this.initMarkers();
}
}
Installing and usage
npm i @kolkov/angular-editor
<angular-editor [(ngModel)]="htmlContent"></angular-editor>
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AngularEditorModule } from '@kolkov/angular-editor';
@Component({
selector: 'app-editor',
templateUrl: './editor.html',
styleUrls: ['./editor.scss'],
standalone: true,
imports: [AngularEditorModule, FormsModule]
})
export class Editor {
public htmlContent = '';
}
Installing and usage
npm i ngx-editor
<div class="NgxEditor__Wrapper">
<ngx-editor-menu [editor]="editor"> </ngx-editor-menu>
<ngx-editor [editor]="editor" [ngModel]="html" [disabled]="false" [placeholder]="'Type here...'"></ngx-editor>
</div>
// component.ts
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Editor, NgxEditorModule } from 'ngx-editor';
@Component({
selector: 'app-editor',
templateUrl: './editor.html',
styleUrls: ['./editor.scss'],
standalone: true,
imports: [ FormsModule,NgxEditorModule]
})
export class Editor implements OnInit {
editor: Editor;
html = '';
constructor() { }
ngOnInit(): void {
this.editor = new Editor();
}
// make sure to destory the editor
ngOnDestroy(): void {
this.editor.destroy();
}
}