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á.