

П��работав с Angular Material 2, в какой то момент пришел к выводу, что продукт сыроват для полета фантазии и некоторые вещи (badge, vertical tabs, data-grid) либо реализованы с минимальным функционалом, либо In progress, planned.
Вечером, придя домой, начал искать что нибудь, что мог бы предложить тимлиду как альтернативу для следующего проекта. Тут то я и заметил, что angular.io разжился табом Resources. Это было пару месяцев назад.
Там среди прочих довольно таки полезных вещей, команда разработчиков Angular, добавила продукт от не менее известной компании, чьи разработки я уважаю и с щенячьим восторгом всегда рад лишний раз поковырять — VmWare. Ребята сделали весьма и весьма достойный продукт — Clarity.
Решил для себя, написать статью на тему Clarity, но просто писать обзор — не хотелось, решил сделать что то вроде starter-kit на случай если кому то понадобится быстро сделать админку. Также, будет активно использоваться Highcharts, Angular Flex-layout и i18n библиотека ngx-translate
Для нетерпеливых: github, demo
Говнокода много, и если встретится подобное, просьба понять, простить и написать комментарий, буду премного благодарен :)
Не буду углубляться в процесс установки Node.js, angular-cli и положу под спойлер инструкцию, на случай если кто-то только начал знакомство с Angular.
установка node.js и angular/cli
Качаем отсюда node.js и ставим.
Выполняем команду для установки angular-cli:
после чего генерируем наш проект:
Выполняем команду для установки angular-cli:
npm install -g @angular/cli
после чего генерируем наш проект:
ng new ngClarity
Итак, у нас уже есть Hello World, далее необходимо подготовить среду, установить пакеты и сконфигурировать наш angular:
Установка
Ставим пакет иконок:
npm install clarity-icons --save
Пакет с полифиллами:
npm install @webcomponents/custom-elements@1.0.0 --save
Добавляем все установленное в конфиг файл .angular-cli.json
"styles": [ "styles.css", "../node_modules/clarity-icons/clarity-icons.min.css" ], "scripts": [ "../node_modules/@webcomponents/custom-elements/custom-elements.min.js", "../node_modules/clarity-icons/clarity-icons.min.js" ],
Дополняем наш Angular модулем clarity-ui:
npm install clarity-ui --save
Лезем обратно в в конфиг файл .angular-cli.json и дописываем путь к стилям clarity-ui:
"styles": [ "styles.css", "../node_modules/clarity-icons/clarity-icons.min.css", "../node_modules/clarity-ui/clarity-ui.min.css" ],
Ставим пакет clarity-angular:
npm install clarity-angular --save
Добавляем импорт в наш app.module.ts:
import { ClarityModule } from "clarity-angular";
И объявляем в imports:
@NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, BrowserAnimationsModule, ClarityModule ], providers: [], bootstrap: [AppComponent] })
Для тех кто привык обращаться только к официальной документации, есть ссылка.
i18n
Далее, думаю стоит описать установку и настройку модуля i18n(используется библиотека ngx-translate), тут ничего необычного, но все же уделим внимание, возможно кому то понадобится:
Ставим либу:
npm install @ngx-translate/core --save npm install @ngx-translate/http-loader --save
идем в наш app.module.ts и дополняем его импортами:
import {TranslateModule, TranslateLoader} from '@ngx-translate/core'; import {TranslateHttpLoader} from '@ngx-translate/http-loader';
имплементация http фактории, которая будет подгружать наши translations файлы:
export function HttpLoaderFactory(http: HttpClient) { return new TranslateHttpLoader(http, './assets/i18n/', '.json'); }
создаем два файла, en.json и ru.json в директории /assets/i18n/
и ставим точку в этом деле, добавляя модуль в imports нашего @NgModule:
TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient] } })
В итоге, мы имеем начальную конфигурацию ngx-translate, и теперь можем объявить в app.component.ts наш TranslationService, который будет подгружать json файлы из директории /assets/i18n
import {Component, OnInit} from '@angular/core'; import {TranslateService} from "@ngx-translate/core"; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ constructor(public translate: TranslateService){} ngOnInit(){ this.translate.addLangs(["en", "ru"]); this.translate.setDefaultLang('en'); let browserLang = this.translate.getBrowserLang(); if (browserLang.match( /en|ru/ )) { this.translate.use( browserLang ); } else { this.translate.use( 'en' ); } } }
Роутинг
Cоздаем роутинг сервис для нашего проекта. В директории /app создаем файл routing.module.ts и конфигурируем наш AppRoutingModule:
import {NgModule}from '@angular/core'; import {Routes, RouterModule}from '@angular/router'; const appRoutes: Routes = [ { path: '', redirectTo: '/', pathMatch: 'full', } ]; @NgModule({ imports: [ RouterModule.forRoot( appRoutes ) ], exports: [ RouterModule ] }) export class AppRoutingModule {}
для инициализации, в app.module.ts, добавляем импорт AppRoutingModule в наш @NgModule.
Компоненты
Создаем три пустых пока что компонента: DashboardComponent, SettingsComponent и PageNotFoundComponent. Внутри app создаем директорию pages, и из под нее запускаем:
ng generate component dashboard ng generate component settings ng generate component pageNotFound
наш angular/cli создаст три директории с указанными именами, создаст внутри директорий все необходимое для компонента и обновит app.module.
Иногда angular/cli может неправильно резолвить пути до файлов, и в случае возникновения ошибок, нужно перепроверить импорты и пути к файлам в app.module.
Далее, заходим в наш routing.module.ts и редактируем роуты для новоиспеченных компонентов:
const appRoutes: Routes = [ { path: 'dashboard', component: DashboardComponent, }, { path: 'settings', component: SettingsComponent, }, { path: '', redirectTo: 'dashboard', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ];
Cтроим каркас нашего приложения. Заходим в app.component.html и начинаем:
<clr-main-container> <clr-header class="header-3"> <div class="branding"> <a href="..." class="nav-link"> <span class="title">ngClarity</span> </a> </div> <div class="header-actions"> <clr-dropdown> <button class="nav-icon" clrDropdownTrigger> <clr-icon shape="world"></clr-icon> <clr-icon shape="caret down"></clr-icon> </button> <clr-dropdown-menu *clrIfOpen clrPosition="bottom-right"> <a *ngFor="let lang of translate.getLangs()" (click)="translate.use(lang)" clrDropdownItem>{{lang}}</a> </clr-dropdown-menu> </clr-dropdown> <clr-dropdown> <button class="nav-icon" clrDropdownTrigger> <clr-icon shape="user"></clr-icon> <clr-icon shape="caret down"></clr-icon> </button> <clr-dropdown-menu *clrIfOpen clrPosition="bottom-right"> <a href="..." clrDropdownItem>{{ 'profile' | translate }}</a> <a href="..." clrDropdownItem>{{ 'logout' | translate }}</a> </clr-dropdown-menu> </clr-dropdown> </div> </clr-header> <div class="alert alert-app-level"></div> <div class="content-container"> <div class="content-area"> <router-outlet></router-outlet> </div> <clr-vertical-nav [clrVerticalNavCollapsible]="true" [clr-nav-level]="1"> <a clrVerticalNavLink routerLink="/dashboard" routerLinkActive="active" class="nav-link"> <clr-icon clrVerticalNavIcon shape="dashboard"></clr-icon>{{ 'dashboard' | translate }} </a> <a clrVerticalNavLink routerLink="/settings" routerLinkActive="active" class="nav-link"> <clr-icon clrVerticalNavIcon shape="cog"></clr-icon>{{ 'settings' | translate }} </a> </clr-vertical-nav> </div> </clr-main-container>
Останавливаться на каждом из директив не будем, для этого есть хорошо написанная документация. Каркас более менее готов, далее можно будет уже работать с компонентами.
Highcharts
Устанавливаем труд товарища cebor, который создал ангуляровскую директиву для Highcharts: angular-highcharts
npm install --save angular-highcharts highcharts
Далее, идем в наш app.module добавляем импорт и объявляем наш модуль, добавив его в imports:
import { ChartModule } from 'angular-highcharts'; @NgModule({ imports: [ ChartModule ] })
Flex-Layout
Теперь возьмемся за flex-layout:
npm install @angular/flex-layout --save
и по традиции, в app.module.ts
import { FlexLayoutModule } from '@angular/flex-layout'; @NgModule({ imports: [ FlexLayoutModule ] })
Теперь, идем в наш dashboard.component.ts объявляем импорты:
import * as Highcharts from 'highcharts'; import * as HichartsExporting from 'highcharts/modules/exporting'; import * as Hicharts3d from 'highcharts/highcharts-3d.js'; HichartsExporting(Highcharts);//объявляем модуль exporting Hicharts3d(Highcharts);//объявляем модуль 3d
В dashboard.component.html рисуем наши блоки, где разместим графики:
<div style="padding: 1em;" fxLayout="row" fxLayout.xs="column" fxLayout.sm="column" fxLayoutWrap fxLayoutGap="1rem" fxLayoutAlign="center"> <div class="card" fxLayout="column" fxLayout.xs="column" fxFlex="49" fxLayout.sm="column" style="padding: 5px;"> <div class="card-block" id="chart1"></div> </div> <div class="card" fxLayout="column" fxLayout.xs="column" fxFlex="49" fxLayout.sm="column" style="padding: 5px;"> <div class="card-block" id="chart2"></div> </div> </div>
и код самого компонента, в dashboard.component.ts:
import { Component, OnInit } from '@angular/core'; import * as Highcharts from 'highcharts'; import * as HichartsExporting from 'highcharts/modules/exporting'; import * as Hicharts3d from 'highcharts/highcharts-3d.js'; HichartsExporting(Highcharts); Hicharts3d(Highcharts); @Component({ selector: 'app-dashboard', templateUrl: './dashboard.component.html', styleUrls: ['./dashboard.component.css'] }) export class DashboardComponent implements OnInit { constructor() { } ngOnInit() { Highcharts.chart('chart1', { chart: { type: 'column' }, title: { text: 'Schedules work progress' }, credits: { enabled: false }, xAxis: { categories: ['line 1', 'line 2', 'line 3', 'line 4'], labels: { skew3d: true, style: { fontSize: '16px' } } }, yAxis: { allowDecimals: false, min: 0, title: { text: 'Total count', skew3d: true } }, tooltip: { headerFormat: '<b>{point.key}</b><br>', pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.percentage:.0f}%)<br/>' }, plotOptions: { column: { stacking: 'normal', depth: 40, dataLabels: { enabled: true, color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white' } } }, series: [ {name: 'Left', data: [10, 58, 23, 8]}, {name: 'Done', data: [27, 98, 44, 65]}, {name: 'Alert', data: [8, 4, 65, 78]} ] }); Highcharts.chart('chart2', { chart: { type: 'pie', options3d: { enabled: true, alpha: 45, beta: 0 } }, title: { text: 'Browser market shares at a specific website, 2014' }, credits: { enabled: false }, tooltip: { pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>' }, plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', depth: 35, dataLabels: { enabled: true, format: '{point.name}' } } }, series: [{ type: 'pie', name: 'Browser share', data: [ ['Firefox', 45.0], ['IE', 26.8], { name: 'Chrome', y: 12.8, sliced: true, selected: true }, ['Safari', 8.5], ['Opera', 6.2], ['Others', 0.7] ] }] }); } }
Сейчас уже можно будет увидеть, что в итоге получилось: demo
На этом, первая часть завершается. Вторая часть статьи будет более детально разбирать компоненты Clarity и реализовывать их в проекте, исходники которого здесь: github
