Prezentácia je k dispozícii tu.
Celý kód si napíšeme spolu, nasledujúce ukážky kódu sú tu v prípade, ak by niekto nestíhal, poprípade si to chcel pozrieť doma. :-)
Prvým krokom je spraviť si appku, ktorá nám vypíše Hello World!, aby sme v rýchlosti pochopili syntax Angularu :-)
Tento kód si napíšeme a vysvetlíme spolu.
Otvoríme príkazový riadok, nainštalujeme angular command line interface, vytvoríme nový projekt a otvoríme ho vo Visual studio code.
npm install -g @angular/cli
ng new my-first-angular
cd my-first-angular
code .
Otvoríme si terminál vo Visual studio code a server spustíme príkazom:
ng serve
Na základe zadania si vytvoríme komponenty, z ktorých sa bude skladať náš projekt.
ng generate component issuesform
ng generate component issuestable
ng generate component label
Vytvoríme si priečinok "model" a následne modely našich entít, ktoré budeme potrebovať:
create new folder model
create new file user.model.ts
create new file label.model.ts
create new file issue.model.ts
Namodelujeme si ich. Používateľ bude identifikovaný menom a emailom. user.model.ts:
export class UserModel { Id: number; Name: string; Email: string; constructor(Id: number, Name: string, Email: string) { this.Id = Id; this.Name = Name; this.Email = Email; } }
Každý label bude identifikovaný názvom, farbou písma a farbou pozadia. label.model.ts:
export class LabelModel { Id: number; Text: string; TextColor: string; BackgroundColor: string; constructor(Id: number, Text: string, TextColor: string, BackgroundColor: string) { this.Id = Id; this.Text = Text; this.TextColor = TextColor; this.BackgroundColor = BackgroundColor; } }
Každá issue(problém) bude identifikovaná dátumom a časom vytvorenia, textom, autorom, komu je daná požiadavka pridelená a tiež danými tagmi. issue.model.ts:
import { UserModel } from "./user.model"; import { LabelModel } from "./label.model"; import * as moment from "moment"; export class IssueModel { Id: number; Time: Date; Text: string; Author: UserModel; AssignedTo: UserModel; Labels: LabelModel[] = []; constructor(Id: number, Time: Date, Text: string, Author: UserModel, AssignedTo: UserModel, Labels: LabelModel[]) { this.Id = Id); this.Time = Time; this.Text = Text; this.Author = Author; this.AssignedTo = AssignedTo; this.Labels = Labels; } getTimeMoment() { return moment(this.Time); } }
Budeme tiež potrebovať service na prácu s našou internou "databázou" (nebudeme si ukazovať sql ani mongodb, podstatou projektu je ukázať si ako funguje angular).
ng generate service "model/issue"
Keďže pracujeme s interným úložiskom, je potrebné si nainicializovať potrebné hodnoty. Určite budeme potrebovať funkcie, ktoré nám vrátia všetky položky daného poľa. issue.service.ts:
import { Injectable } from '@angular/core'; import { IssueModel } from './issue.model'; import { UserModel } from './user.model'; import { LabelModel } from './label.model'; @Injectable({ providedIn: 'root' }) export class IssueService { private _issueDatabase: IssueModel[] = null; private _issueDatabaseId: number = 2; private _userDatabase: UserModel[] = null; private _labelDatabase: LabelModel[] = null; constructor() { if (this._issueDatabase == null) { } this.initialize(); } initialize() { this._userDatabase = [ new UserModel(1, "Jozko", "jozko.mrkvicka@upjs.sk"), new UserModel(2, "Evka", "eva.markova@upjs.sk"), ]; this._labelDatabase = [ new LabelModel(1, "angular", "white", "red"), new LabelModel(2, "reactjs", "white", "blue"), new LabelModel(3, "python", "white", "green") ]; this._issueDatabase = [ new IssueModel(1, new Date(), "Issue1", this.getUserById(1), this.getUserById(1), [ this.getLabelById(1)]), new IssueModel(2, new Date(), "Issue2", this.getUserById(2), this.getUserById(1), [ this.getLabelById(1), this.getLabelById(2)]) ]; } getLabelById(id: number): LabelModel { for (let label of this._labelDatabase) { if (label.Id == id) { return label; } } return null; } getUserById(id: number): UserModel { for (let user of this._userDatabase) { if (user.Id == id) { return user; } } return null; } getIssueById(id:number): IssueModel { for (let issue of this._issueDatabase) { if (issue.Id == id) { return issue; } } return null; } getAllUsers(): UserModel[] { return this._userDatabase; } getAllLabels(): LabelModel[] { return this._labelDatabase; } getAllIssues(): IssueModel[] { return this._issueDatabase; } addOrChangeIssue(model: IssueModel): boolean { model.Id = ++this._issueDatabaseId; model.Time = new Date(); this._issueDatabase.push(model); return true; } }
Na vstupe očakávame label. label.component.ts:
import { Component, OnInit, Input } from '@angular/core'; import { LabelModel } from '../model/label.model'; @Component({ selector: 'app-label', templateUrl: './label.component.html', styleUrls: ['./label.component.css'] }) export class LabelComponent implements OnInit { @Input() label: LabelModel; constructor() { } ngOnInit() { } }
Dopredu si nadefinujeme ako bude vyzerať "výpis" konkrétneho labelu. label.component.html:
{{label.Text}}
Do premennej issues si uložíme všetky issues. issuestable.component.ts:
import { Component, OnInit } from '@angular/core'; import { IssueModel } from '../model/issue.model'; import { IssueService } from '../model/issue.service'; import { Router } from '@angular/router'; @Component({ selector: 'app-issuestable', templateUrl: './issuestable.component.html', styleUrls: ['./issuestable.component.css'] }) export class IssuestableComponent implements OnInit { protected issues: IssueModel[] = []; constructor(private issueService: IssueService, private router: Router) { } ngOnInit() { this.issues = this.issueService.getAllIssues(); console.log(this.issues); } }
V issuestable.component.html si naformátujeme výpis všetkých issues.
ID | Čas | Názov | Autor | Pridelené | Tagy | Akcie |
---|---|---|---|---|---|---|
{{issue.Id}} | {{issue.getTimeMoment().format("D.MMM.YYYY h:mm:ss")}} | {{issue.Text}} | {{issue.Author.Name}} | {{issue.AssignedTo.Name}} |
|
Na vytvorenie úplne novej issue použijeme nový komponent. V podstate si ideme zadefinovať, akú bude mať funkcionalitu a ako bude vyzerať issue formulár. issuesform.component.ts:
import { Component, OnInit } from '@angular/core'; import { IssueModel } from '../model/issue.model'; import { IssueService } from '../model/issue.service'; import { LabelModel } from '../model/label.model'; import { UserModel } from '../model/user.model'; import { ActivatedRoute, Router } from '@angular/router'; @Component({ selector: 'app-issuesform', templateUrl: './issuesform.component.html', styleUrls: ['./issuesform.component.css'] }) export class IssuesformComponent implements OnInit { protected model: IssueModel = new IssueModel(); protected labels: LabelModel[]; protected users: UserModel[]; protected modelLabelsAssigns: {}; constructor(private route: ActivatedRoute, private router: Router, private issueService: IssueService) { } ngOnInit() { let id = this.route.snapshot.paramMap.get('id'); this.labels = this.issueService.getAllLabels(); this.users = this.issueService.getAllUsers(); this.modelLabelsAssigns = {}; this.labels.forEach(label => { this.modelLabelsAssigns[label.Id] = false; }); } onSubmit() { this.model.Labels = []; this.labels.forEach(label => { if (this.modelLabelsAssigns[label.Id]) { this.model.Labels.push(label); } }); if (this.issueService.addOrChangeIssue(this.model)) { this.router.navigate(["/issues"]); } } }
Tiež musíme prepísať html súbor. issuesform.component.html:
Issue formulár
V app-routing.module.ts si potrebujeme nadefinovať cesty.
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Routes, RouterModule } from '@angular/router'; import { IssuestableComponent } from './issuestable/issuestable.component'; import { IssuesformComponent } from './issuesform/issuesform.component'; const routes: Routes = [ { path: 'issues', component: IssuestableComponent }, { path: 'issues/create', component: IssuesformComponent }, { path: '**', redirectTo: '/issues' }, ]; @NgModule({ imports: [CommonModule, RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
app.component.html bude vyzerať nasledovne:
Do app.module.ts doplníme do imports FormModules.
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { IssuesformComponent } from './issuesform/issuesform.component'; import { IssuestableComponent } from './issuestable/issuestable.component'; import { LabelComponent } from './label/label.component'; @NgModule({ declarations: [ AppComponent, IssuesformComponent, IssuestableComponent, LabelComponent ], imports: [ BrowserModule, FormsModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Ale čo ak chceme editovať už pridanú issue? Do issuestable.component.ts pridáme:
editIssue(issue?: IssueModel) { this.router.navigate(["/issues/edit", issue.Id]); }
V issuesform.component.ts musíme v metóde ngOnInit() ošetriť, ak daná issue už existovala.
if (id) { this.model = this.issueService.getIssueById(Number(id)); this.model.Labels.forEach(selected => { this.modelLabelsAssigns[selected.Id] = true; }); }
Pridáme tlačidlo do issuestable.component.html
Tiež je treba aktualizovať issue.service.ts:
addOrChangeIssue(model: IssueModel): boolean { if (model.Id != null) { let search = null; this._issueDatabase.forEach(item => { if (item.Id == model.Id) { search = item; } }); let indexOf = this._issueDatabase.indexOf(search); this._issueDatabase.splice(indexOf, 1); } else { model.Id = ++this._issueDatabaseId; model.Time = new Date(); } this._issueDatabase.push(model); return true; }
Samozrejme nesmieme zabudnúť na nadefinovanie cesty.
{ path: 'issues/edit/:id', component: IssuesformComponent }
Ak chceme pekný dizajn, môžeme použiť knižnicu bootstrap.
npm install bootstrap
V súbore angular.json doplníme "styles" takto:
"styles": [ "node_modules/bootstrap/dist/css/bootstrap.min.css", "src/styles.css" ],
Do styles.css pridáme nasledujúci import:
@import '~bootstrap/dist/css/bootstrap.min.css';
Úlohy
-
Pridajte funkcionalitu vymazania issue (teda doplňte "delete" operáciu).
Hint: Na vymazanie z našej lokálnej "databázy" funguje príkaz nazov_db.splice(index_mazaneho, 1) - Pridajte atribút priorita (pomocou modelu PriorityModel) pre issues s možnosťou výberu nízka, stredná a vysoká.