Component
Abstract Elements
In theme we are using Abstract Elements for calling small widgets. so It will easy to use and user freindlly from developer perspective.
Basic UI Elements
<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
<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>
<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 tag-pills-sm-mb">Dark</span>
<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 class="btn btn-primary example-popover" type="button" placement="left" popoverTitle="Basic Popover" ngbPopover="If the package restore doesn't help, you can look at the Output window in the Visual Studio.">Hurry Up! </button>
<button class="example-popover btn btn-warning" type="button" placement="bottom" popoverTitle="Hover Popover" data-offset="-20px -20px" ngbPopover=" Several utility instruction sets have been featured in the Bootstrap 4 to promote very easy learning for beginners in the business of web building.">Hover tooltip</button>
<a class="btn btn-lg btn-secondary" tabindex="0" role="button" placement="right" popoverTitle="Dismissible popover" ngbPopover="You are able to even develop and suggest improvements to the Bootstrap 4 before its final version is delivered.">Dismissible popover</a>
// tooltip.component.html //
<button class="example-popover btn btn-primary" type="button" data-bs-placement="top" title="Popover title"
ngbTooltip="Basic Tooltip">
Hover Me
</button>
// tooltip.component.ts //
@Component({
selector: 'tooltip',
templateUrl: './tooltip.component.html'
})
export class TooltipComponent {
name = 'World';
}
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 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
<div class="card-body">
<ngbNav #nav="ngbNav" [activeId]="1" class="nav nav-tabs">
<li class="nav-item" [ngbNavItem]="1">
<a class="nav-link" ngbNavLink>Home</a>
<ng-template ngbNavContent>
<p>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</p>
</ng-template>
</li>
<li ngbDropdown class="nav-item dropdown">
<a class="nav-link dropdown-toggle bg-transparent border-none" (click)="isShow = !isShow" ngbDropdownToggle>Dropdown</a>
<div class="dropdown-menu" ngbDropdownMenu [ngClass]="isShow ? 'd-block':'d-none'">
<button class="dropdown-item" ngbDropdownItem>Action</button>
<button class="dropdown-item" ngbDropdownItem>Another action</button>
<button class="dropdown-item" ngbDropdownItem>Something else here</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item" ngbDropdownItem>Separated link</button>
</li>
<li class="nav-item" [ngbNavItem]="2">
<a class="nav-link" ngbNavLink>Profile</a>
<ng-template ngbNavContent>
<p>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
</p>
</ng-template>
</li>
<li class="nav-item" [ngbNavItem]="3">
<a class="nav-link" ngbNavLink>Profile</a>
<ng-template ngbNavContent>
<p>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
</p>
</ng-template>
</li>
<li class="nav-item" [ngbNavItem]="4">
<a class="nav-link" ngbNavLink>Contact</a>
<ng-template ngbNavContent>
<p>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
</p>
</ng-template>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div [ngbNavOutlet]="nav" class="mt-4">
</div>
</div>
<div ngbAccordion [closeOthers]="true">
@for (item of items; track item) {
<div ngbAccordionItem [collapsed]="item !== 'First'">
<h2 ngbAccordionHeader>
<button ngbAccordionButton>{{ item }}</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-static',
standalone: true,
imports: [NgbAccordionModule],
templateUrl: './accordion-static.html',
})
export class NgbdAccordionStatic {
items = ['First', 'Second', 'Third'];
}
Advance UI Elements
Installing and usage
npm i ngx-bar-rating
// rating.component.html
<bar-rating class="bar" [(rate)]="faRate" [max]="10" [theme]="'horizontal'" [showText]="true"></bar-rating>
// rating.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-rating-bar',
templateUrl: './rating-bar.component.html',
styleUrls: ['./rating-bar.component.scss']
})
export class RatingBarComponent {
public faRate = 7;
}
Installing and usage
npm i sweetalert2
// sweet-alert2.component.html
<button class="btn btn-primary sweet-1" type="button" (click)="basicAlert()">Click it!</button>
// sweet-alert2.component.ts
import { Component } from '@angular/core';
import Swal from 'sweetalert2';
@Component({
selector: 'app-basic',
templateUrl: './basic.component.html',
styleUrls: ['./basic.component.scss']
})
export class BasicComponent {
basicAlert(){
Swal.fire({
title : 'Welcome! to the Yuri theme',
confirmButtonColor : 'var(--theme-deafult)',
})
}
}
Installing and usage
npm i @angular-slider/ngx-slider
// range-slider.component.html //
<ngx-slider [(value)]="value" [options]="options"></ngx-slider>
// range-slider.components.ts //
import { Component } from '@angular/core';
import { Options } from 'ngx-slider-v2';
@Component({
selector: 'app-default-slider',
templateUrl: './default-slider.component.html',
styleUrls: ['./default-slider.component.scss']
})
export class DefaultSliderComponent {
public value: number = 550;
public options: Options = {
floor: 100,
ceil: 1000,
};
}
Installing and usage
npm i ngx-dropzone
// dropzone.component.html
<ngx-dropzone (change)="onSelect($event)">
<ngx-dropzone-label>Drag & Drop your files or Browse</ngx-dropzone-label>
@for (f of files; track f) {
<ngx-dropzone-preview [removable]="true" (removed)="onRemove(f)">
<ngx-dropzone-label>{{ f.name }} ({{ f.type }})</ngx-dropzone-label>
</ngx-dropzone-preview>
}
</ngx-dropzone>
// dropzone.component.ts
public files: File[] = [];
onSelect(event: NgxDropzoneChangeEvent) {
this.files.push(...event.addedFiles);
}
onRemove(event: File) {
this.files.splice(this.files.indexOf(event), 1);
}
Forms
Installing and usage
npm i @ng-bootstrap/ng-bootstrap
//forms-widgets.module.ts //
import { NgbCalendar, NgbDatepickerModule, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'ngbd-datepicker-basic',
standalone: true,
imports: [NgbDatepickerModule, FormsModule],
templateUrl: './datepicker-basic.html',
})
export class NgbdDatepickerBasic {
model: NgbDateStruct;
}
//date-time-picker.component.html //
<ngb-datepicker #dp [(ngModel)]="model" (navigate)="date = $event.next" />
Installing and usage
npm i @ng-bootstrap/ng-bootstrap
<input id="typeahead-basic" type="text" class="form-control" [(ngModel)]="model" [ngbTypeahead]="search" />
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: any;
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),
),
);
}
Tables
# | First | Last | Handle |
---|---|---|---|
1 | Mark | Otto | @mdo |
2 | Jacob | Thornton | @fat |
3 | Larry the Bird |
Installing and usage
npm i bootstrap
<table class="table">
<thead>
<tr>
<th scope="col"># </th>
<th scope="col">First </th>
<th scope="col">Last </th>
<th scope="col">Handle </th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1 </th>
<td>Mark </td>
<td>Otto </td>
<td>@mdo </td>
</tr>
<tr>
<th scope="row">2 </th>
<td>Jacob </td>
<td>Thornton </td>
<td>@fat </td>
</tr>
<tr>
<th scope="row">3 </th>
<td colspan="2">Larry the Bird </td>
<td>@twitter </td>
</tr>
</tbody>
</table>
Installing and usage
npm i @ng-bootstrap/ng-bootstrap
// data.ts
export const basicDataTable: Table[] = [
{
id: 1,
name: 'Tiger Nixon',
position: 'System Architect',
office: 'Edinburgh',
age: '61',
startDate: '2011/04/25',
salary: '$320,800',
},
{
id: 2,
name: 'Garrett Winters',
position: 'Accountant',
office: 'Tokyo',
age: '63',
startDate: '2011/07/25',
salary: '$170,750',
},
{
id: 3,
name: 'Ashton Cox',
position: 'Junior Technical Author',
office: 'San Francisco',
age: '66',
startDate: '2009/01/12',
salary: '$86,000',
},
{
id: 4,
name: 'Cedric Kelly',
position: 'Senior Javascript Developer',
office: 'Edinburgh',
age: '22',
startDate: '2012/03/29',
salary: '$433,060',
},
{
id: 5,
name: 'Airi Satou',
position: 'Accountant',
office: 'Tokyo ',
age: '33',
startDate: '2008/11/28',
salary: '$162,700',
},
{
id: 6,
name: 'Brielle Williamson',
position: 'Integration Specialist',
office: 'New York ',
age: '61',
startDate: '2012/12/02',
salary: '$372,000',
},
{
id: 7,
name: 'Herrod Chandler',
position: 'Sales Assistant',
office: 'San Francisco',
age: '59',
startDate: '2012/08/06',
salary: '$137,500',
},
{
id: 8,
name: 'Rhona Davidson',
position: 'Integration Specialist',
office: 'Tokyo',
age: '55',
startDate: '2010/10/14',
salary: '$327,900',
},
{
id: 9,
name: 'Colleen Hurst',
position: 'Javascript Developer',
office: 'San Francisco',
age: '39',
startDate: '2009/09/15',
salary: '$205,500',
},
{
id: 10,
name: 'Sonya Frost',
position: 'Software Engineer',
office: 'Edinburgh',
age: '23',
startDate: '2008/12/13',
salary: '$103,600',
},
{
id: 11,
name: 'Jena Gaines',
position: 'Office Manager',
office: 'London',
age: '30',
startDate: '2008/12/19',
salary: '$90,560',
},
{
id: 12,
name: 'Quinn Flynn',
position: 'Support Lead',
office: 'Edinburgh',
age: '22',
startDate: '2013/03/03',
salary: '$342,000',
},
{
id: 13,
name: 'Charde Marshall',
position: 'Regional Director',
office: 'San Francisco',
age: '36',
startDate: '2008/10/16',
salary: '$470,600',
},
{
id: 14,
name: 'Donna Snider',
position: 'Customer Support',
office: 'New York',
age: '27',
startDate: '2011/01/25',
salary: '$112,000',
},
];
// countries.service.ts
import { Injectable, PipeTransform } from '@angular/core';
import { Table, basicDataTable } from '../data/data/table/data-table';
import { BehaviorSubject, Observable, Subject, debounceTime, delay, of, switchMap, tap } from 'rxjs';
import { DecimalPipe } from '@angular/common';
import { SortColumn, SortDirection } from '../directives/basic-data-table.directive';
interface SearchResult {
baiscTable: Table[];
total: number;
}
interface State {
page: number;
pageSize: number;
searchTerm: string;
sortColumn: SortColumn;
sortDirection: SortDirection;
}
function sort(baiscTable: Table[], column: SortColumn, direction: string): Table[] {
if (direction === '' || column === '') {
return baiscTable;
} else {
return [...baiscTable].sort((a, b) => {
const res = compare(a[column], b[column]);
return direction === 'asc' ? res : -res;
});
}
}
const compare = (v1: string | number, v2: string | number) => (v1 < v2 ? -1 : v1 > v2 ? 1 : 0);
function matches(table: Table, term: string, pipe: PipeTransform) {
return (
table.name.toLowerCase().includes(term.toLowerCase()) ||
table.position.toLowerCase().includes(term.toLowerCase()) ||
table.office.toLowerCase().includes(term.toLowerCase()) ||
table.startDate.toLowerCase().includes(term.toLowerCase()) ||
table.salary.toLowerCase().includes(term.toLowerCase()) ||
pipe.transform(table.age).includes(term)
)
}
@Injectable({
providedIn: 'root'
})
export class BasicDataTableService {
private _loading$ = new BehaviorSubject(true);
private _search$ = new Subject();
private _orderList$ = new BehaviorSubject([]);
private _total$ = new BehaviorSubject(0);
private _basic: State = {
page: 1,
pageSize: 10,
searchTerm: '',
sortColumn: '',
sortDirection: '',
};
constructor(private pipe: DecimalPipe) {
this._search$
.pipe(
tap(() => this._loading$.next(true)),
debounceTime(200),
switchMap(() => this._search()),
delay(200),
tap(() => this._loading$.next(false)),
)
.subscribe((result) => {
this._orderList$.next(result.baiscTable);
this._total$.next(result.total);
});
this._search$.next();
}
get basicDataTable$() {
return this._orderList$.asObservable();
}
get total$() {
return this._total$.asObservable();
}
get loading$() {
return this._loading$.asObservable();
}
get page() {
return this._basic.page;
}
get pageSize() {
return this._basic.pageSize;
}
get searchTerm() {
return this._basic.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._basic, patch);
this._search$.next();
}
private _search(): Observable {
const { sortColumn, sortDirection, pageSize, page, searchTerm } = this._basic;
// 1. sort
let baiscTable = sort(basicDataTable, sortColumn, sortDirection);
// 2. filter
baiscTable = baiscTable.filter((list) => matches(list, searchTerm, this.pipe));
const total = baiscTable.length;
// 3. paginate
baiscTable = baiscTable.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
return of({ baiscTable, total });
}
}
//interface
export interface Table {
id: number;
name: string;
position: string;
office: string;
startDate: string;
salary: string;
age: string;
}
// table-component.html
<div class="table-responsive custom-scrollbar">
<div class="dataTables_wrapper no-footer">
<div class="mb-3 row">
<label for="table-complete-search"
class="col-xs-3 col-sm-auto col-form-label">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="display dataTable" id="basic-1">
<thead>
<tr>
<th sortableDefault="name" (sort)="onSort($event)">Name</th>
<th sortableDefault="position" (sort)="onSort($event)">Position</th>
<th sortableDefault="office" (sort)="onSort($event)">Office</th>
<th sortableDefault="age" (sort)="onSort($event)">Age</th>
<th sortableDefault="startDate" (sort)="onSort($event)">Start date</th>
<th sortableDefault="salary" (sort)="onSort($event)">Salary</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@for (item of basicDataTable$ | async; track item) {
<tr>
<td>{{item.name}}</td>
<td>{{item.position}}</td>
<td>{{item.office}}</td>
<td>{{item.age}}</td>
<td>{{item.startDate}}</td>
<td>{{item.salary}}</td>
<td>
<ul class="action">
<li class="edit">
<a href="javascript:void(0)">
<i class="icon-pencil-alt"></i>
</a>
</li>
<li class="delete">
<a href="javascript:void(0)">
<i class="icon-trash"></i>
</a>
</li>
</ul>
</td>
</tr>
}
@if (basicData.length === 0) {
<tr>
<td>No matching records found</td>
</tr>
}
</tbody>
</table>
<div class="d-flex justify-content-between p-2">
<select class="form-select" style="width: auto" name="pageSize"
[(ngModel)]="service.pageSize">
<option [ngValue]="10">10 items per page</option>
<option [ngValue]="25">25 items per page</option>
<option [ngValue]="50">50 items per page</option>
<option [ngValue]="100">100 items per page</option>
</select>
<ngb-pagination [collectionSize]="(total$ | async)!" [(page)]="service.page"
[pageSize]="service.pageSize"> </ngb-pagination>
</div>
</div>
</div>
// table-component.ts
import { DecimalPipe } from '@angular/common';
import { Component, QueryList, ViewChildren } from '@angular/core';
import { Observable } from 'rxjs';
import { Table } from '../../../shared/data/data/table/data-table';
import { BasicDataTableDirective, SortEvent } from '../../../shared/directives/basic-data-table.directive';
import { BasicDataTableService } from '../../../shared/services/basic-data-table.service';
@Component({
selector: 'app-data-tables',
templateUrl: './data-tables.component.html',
styleUrls: ['./data-tables.component.scss'],
providers: [BasicDataTableService, DecimalPipe],
})
export class DataTablesComponent {
public isShow: boolean = false;
public basicDataTable$: Observable;
public total$: Observable;
public basicData: Table[];
@ViewChildren(BasicDataTableDirective)
public headers: QueryList;
constructor(public service: BasicDataTableService) {
this.basicDataTable$ = service.basicDataTable$;
this.total$ = service.total$;
}
ngOnInit() {
this.service.basicDataTable$.subscribe((data) => {
if (data) {
this.basicData = data;
}
});
}
onSort({ column, direction }: SortEvent) {
this.headers.forEach((header) => {
if (header.sortableDefault !== column) {
header.direction = "";
}
});
this.service.sortColumn = column;
this.service.sortDirection = direction;
}
}
// sortable.directive.ts
import { Directive, EventEmitter, Input, Output } from '@angular/core';
import { Table } from '../data/data/table/data-table';
export type SortColumn = keyof Table | '';
export type SortDirection = 'asc' | 'desc' | '';
const rotate: {[key: string]: SortDirection} = { 'asc': 'desc', 'desc': '', '': 'asc' };
export interface SortEvent {
column: SortColumn;
direction: SortDirection;
}
@Directive({
selector: 'th[sortableDefault]',
standalone: true,
host: {
'[class.asc]': 'direction === "asc"',
'[class.desc]': 'direction === "desc"',
'(click)': 'rotate()',
},
})
export class BasicDataTableDirective {
constructor() { }
@Input() sortableDefault: SortColumn = '';
@Input() direction: SortDirection = '';
@Output() sort = new EventEmitter();
rotate() {
this.direction = rotate[this.direction];
this.sort.emit({ column: this.sortableDefault, direction: this.direction });
}
}
Supplemental
Charts
Installing and usage
npm i ng-apexcharts
// basic-aria-chart.component.html //
<apx-chart [chart]="basicAreaChart.chart" [dataLabels]="basicAreaChart.dataLabels"
[stroke]="basicAreaChart.stroke" [series]="basicAreaChart.series" [title]="basicAreaChart.title"
[subtitle]="basicAreaChart.subtitle" [labels]="basicAreaChart.labels" [xaxis]="basicAreaChart.xaxis"
[yaxis]="basicAreaChart.yaxis" [legend]="basicAreaChart.legend" [colors]="basicAreaChart.colors">
// basic-aria-chart.component.ts //
import { Component } from '@angular/core';
import { basicAreaChart } from '../../../../shared/data/chart/charts/apex-charts';
@Component({
selector: 'app-basic-area-chart',
templateUrl: './basic-area-chart.component.html',
styleUrls: ['./basic-area-chart.component.scss']
})
export class BasicAreaChartComponent {
public basicAreaChart = basicAreaChart ;
}
// data files //
export type ChartOptions = {
series?: ApexAxisChartSeries;
chart?: ApexChart;
xaxis?: ApexXAxis;
stroke?: ApexStroke;
tooltip?: any;
dataLabels?: ApexDataLabels;
hover?: number;
yaxis?: ApexYAxis;
legend?: ApexLegend;
labels?: string[];
plotOptions?: ApexPlotOptions;
fill?: ApexFill;
responsive?: ApexResponsive[];
pieseries?: ApexNonAxisChartSeries;
title?: ApexTitleSubtitle;
theme?: ApexTheme;
colors?: string[];
markers?: ApexMarkers;
annotations?: ApexAnnotations;
grid?: ApexGrid;
};
export let basicAreaChart: ChartOptions | any = {
chart: {
height: 350,
type: "area",
zoom: {
enabled: false,
},
toolbar: {
show: false,
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: "straight",
},
series: [
{
name: "STOCK ABC",
data: series.monthDataSeries1.prices,
},
],
title: {
text: "Fundamental Analysis of Stocks",
align: "left",
},
subtitle: {
text: "Price Movements",
align: "left",
},
labels: series.monthDataSeries1.dates,
xaxis: {
type: "datetime",
},
yaxis: {
opposite: true,
},
legend: {
horizontalAlign: "left",
},
colors: [primary],
}
Supplemental
Installing and usage
npm i ng2-google-charts
// googl-chart.component.html //
<google-chart [data]="areaChart1"></google-chart>
//googl-chart.component.ts //
import { Component } from '@angular/core';
import { areaChart1 } from '../../../../shared/data/chart/charts/google-charts';
@Component({
selector: 'app-area-chart-first',
templateUrl: './area-chart-first.component.html',
styleUrls: ['./area-chart-first.component.scss']
})
export class AreaChartFirstComponent {
public areaChart1 = areaChart1;
}
// data //
import { GoogleChartType } from "ng2-google-charts";
var primary = localStorage.getItem('primary_color') || '#009DB5';
var secondary = localStorage.getItem('secondary_color') || '#F94C8E';
export const areaChart1 = {
chartType: "AreaChart",
dataTable: [
["Year", "Sales", "Expenses"],
["2013", 1000, 400],
["2014", 1170, 460],
["2015", 660, 1120],
["2016", 1030, 540],
],
options: {
title: "Company Performance",
hAxis: { title: "Year", titleTextStyle: { color: "#333" } },
vAxis: { minValue: 0 },
width: "100%",
height: 400,
colors: [primary, secondary],
},
};
Supplemental
Installing and usage
npm i ng2-charts
//bars-charts.component.html//
<canvas baseChart id="myBarGraph" class="chart" [datasets]="barChartChartData" [labels]="barChartChartLabels"
[options]="barChartChartOptions" [legend]="barChartChartLegend" [type]="barChartChartType"></canvas>
//bars-charts.component.ts//
import { Component } from '@angular/core';
import { barChartChartColors, barChartChartData, barChartChartLabels, barChartChartLegend, barChartChartOptions, barChartChartType } from '../../../../shared/data/chart/charts/chart-js';
@Component({
selector: 'app-chart-js-bar-chart',
templateUrl: './chart-js-bar-chart.component.html',
styleUrls: ['./chart-js-bar-chart.component.scss']
})
export class ChartJsBarChartComponent {
public barChartChartLabels = barChartChartLabels;
public barChartChartData = barChartChartData;
public barChartChartType = barChartChartType;
public barChartChartColors = barChartChartColors;
public barChartChartOptions = barChartChartOptions;
public barChartChartLegend = barChartChartLegend;
}
// chartjs-data.ts //
export var barChartChartLabels: string[] = [
"January", "February", "March", "April", "May", "June", "July"
];
export var barChartChartType: ChartType | any = "bar";
export var barChartChartLegend = false;
export var barChartChartOptions: any = {
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,
};
export var barChartChartColors: any[] = [
// { backgroundColor: [primary, secondary] },
];
export var barChartChartData: any[] = [
{
label: "My First dataset",
fillColor: "rgba(0, 157 ,181, 0.4)",
strokeColor: primary,
highlightFill: "rgba(0, 157 ,181, 0.6)",
highlightStroke: primary,
data: [35, 59, 80, 81, 56, 55, 40],
},
{
label: "My Second dataset",
fillColor: "rgba(249, 76, 142, 0.4)",
strokeColor: secondary,
highlightFill: "rgba(249, 76, 142, 0.6)",
highlightStroke: secondary,
data: [28, 48, 40, 19, 86, 27, 90],
},
];
Supplemental
Installing and usage
npm i ng-chartist
// chart-list.html
<x-chartist [configuration]="chart1"></x-chartist>
// chart-list.ts
import { Component } from '@angular/core';
import { chart1 } from '../../../../shared/data/chart/charts/chartist';
@Component({
selector: 'app-advanced-smil-animations',
templateUrl: './advanced-smil-animations.component.html',
styleUrls: ['./advanced-smil-animations.component.scss']
})
export class AdvancedSMILAnimationsComponent {
public chart1 = chart1;
}
// chartlist chart data
import * as Chartist from 'chartist';
var seq: number = 0;
var delays: number = 80;
var durations: number = 500;
var primary = localStorage.getItem('primary_color') || '#009DB5';
var secondary = localStorage.getItem('secondary_color') || '#F94C8E';
export const chart1: any = {
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: 400,
width: 700,
colors: [primary, secondary],
},
events: {
draw: (data: any) => {
seq++;
if (data.type === "line") {
data.element.animate({
opacity: {
begin: seq * delays + 1000,
dur: durations,
from: 0,
to: 1,
},
});
} else if (data.type === "label" && data.axis === "x") {
data.element.animate({
y: {
begin: seq * delays,
dur: durations,
from: data.y + 100,
to: data.y,
easing: "easeOutQuart",
},
});
} else if (data.type === "label" && data.axis === "y") {
data.element.animate({
x: {
begin: seq * delays,
dur: durations,
from: data.x - 100,
to: data.x,
easing: "easeOutQuart",
},
});
} else if (data.type === "point") {
data.element.animate({
x1: {
begin: seq * delays,
dur: durations,
from: data.x - 10,
to: data.x,
easing: "easeOutQuart",
},
x2: {
begin: seq * delays,
dur: durations,
from: data.x - 10,
to: data.x,
easing: "easeOutQuart",
},
opacity: {
begin: seq * delays,
dur: durations,
from: 0,
to: 1,
easing: "easeOutQuart",
},
});
} else if (data.type === "grid") {
var pos1Animation = {
begin: seq * delays,
dur: durations,
from: data[data.axis.units.pos + "1"] - 30,
to: data[data.axis.units.pos + "1"],
easing: "easeOutQuart",
};
var pos2Animation = {
begin: seq * delays,
dur: durations,
from: data[data.axis.units.pos + "2"] - 100,
to: data[data.axis.units.pos + "2"],
easing: "easeOutQuart",
};
var animations: any = {};
animations[data.axis.units.pos + "1"] = pos1Animation;
animations[data.axis.units.pos + "2"] = pos2Animation;
animations["opacity"] = {
begin: seq * delays,
dur: durations,
from: 0,
to: 1,
easing: "easeOutQuart",
};
data.element.animate(animations);
}
},
},
};
Supplemental
Maps
Installing and usage
npm i @angular/google-maps
// google-map.component.html
<google-map width="100%" height="500px" [zoom]="zoom">
@for (marker of markers; track marker) {
<map-marker [position]="marker.position" [label]="marker.label">
</map-marker>
}
</google-map>
// google-map.component.ts
import { Component, ViewChild } from '@angular/core';
import { GoogleMap } from '@angular/google-maps';
@Component({
selector: 'app-googl-map',
templateUrl: './googl-map.component.html',
styleUrl: './googl-map.component.scss'
})
export class GooglMapComponent {
public openInfo: any;
public markers: any[];
public markers1: any[];
public zoom: number;
public bangalore = { lat: 12.97, lng: 77.59 };
constructor() {
this.markers = [];
this.zoom = 2;
}
ngOnInit() {
this.markers1.push({
position: {
lat: 12.97,
lng: 77.59
},
label: {
color: "red",
text: "Arial"
},
Option: {
draggable: true,
animation: google.maps.Animation.DROP,
zoomControl: false,
mapTypeControl: false,
streetViewControl: false,
fullscreenControl: false
}
});
const map = new google.maps.Map(
document.getElementById("map") as HTMLElement,
{
zoom: 12,
center: this.bangalore,
}
);
this.markers.push({
position: {
lat: 35.717,
lng: 139.731
},
label: {
color: "black",
text: "Madrid"
},
Option: {
draggable: true,
animation: google.maps.Animation.DROP,
}
});
this.markers.push({
position: {
lat: 48.8615515,
lng: 2.3112233
},
label: {
color: "black",
text: "Paris"
}
});
}
//Street View
@ViewChild(GoogleMap) map!: GoogleMap;
ngAfterViewInit() {
const streetView = this.map.getStreetView();
streetView.setOptions({
position: { lat: 38.9938386, lng: -77.2515373 },
pov: { heading: 70, pitch: -10 },
});
streetView.setVisible(true);
const bounds = this.getBounds(this.markers);
}
marker1 = { position: { lat: 38.9987208, lng: -77.2538699 } };
marker2 = { position: { lat: 39.7, lng: -76.0 } };
marker3 = { position: { lat: 37.9, lng: -76.8 } };
markers5 = [this.marker1, this.marker2, this.marker3];
getBounds(markers: any[]) {
let north;
let south;
let east;
let west;
for (const marker of markers) {
north = north !== undefined ? Math.max(north, marker.position.lat) : marker.position.lat;
south = south !== undefined ? Math.min(south, marker.position.lat) : marker.position.lat;
east = east !== undefined ? Math.max(east, marker.position.lng) : marker.position.lng;
west = west !== undefined ? Math.min(west, marker.position.lng) : marker.position.lng;
};
const bounds = { north, south, east, west };
return bounds;
}
}
Supplemental
Installing and usage
npm i @asymmetrik/ngx-leaflet
// leaflet-map.component.html
<div style="height: 500px; z-index: 0;" leaflet [leafletOptions]="options1"></div>
import { Component } from '@angular/core';
import * as L from 'leaflet';
@Component({
selector: 'app-leaflet-map',
templateUrl: './leaflet-map.component.html',
styleUrl: './leaflet-map.component.scss'
})
export class LeafletMapComponent {
// First map options
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),
};
}
Supplemental
Editors
Installing and usage
npm i ngx-editor
// ngx-editors.component.html
<ngx-editor-menu [editor]="editor"> </ngx-editor-menu>
<ngx-editor [editor]="editor" [ngModel]="html" [disabled]="false" [placeholder]="'Type here...'"></ngx-editor>
// ngx-editors.component.ts
import { Component } from '@angular/core';
import { Editor } from 'ngx-editor';
@Component({
selector: 'app-ngx-editor',
templateUrl: './ngx-editor.component.html',
styleUrl: './ngx-editor.component.scss'
})
export class NgxEditorComponent {
public editor: Editor;
public html = '';
ngOnInit(): void {
this.editor = new Editor();
}
ngOnDestroy(): void {
this.editor.destroy();
}
}
Supplemental
Installing and usage
@kolkov/angular-editor
// mde-editors.component.html
<angular-editor [placeholder]="'Enter text here...'" [(ngModel)]="htmlContent"></angular-editor>
// mde-editors.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-mde-editors',
templateUrl: './mde-editors.component.html',
styleUrls: ['./mde-editors.component.scss']
})
export class MdeEditorsComponent {
public htmlContent = '';
}
Supplemental