We're going to add the following files to setup our Angular 2 UI :-
- \app\main.ts (Bootstrap code for our application)
- \app\NotesListComponent.ts (This is our component class we're using for CRUD)
- \app\Services\NotesService.ts (Service layer to interact with Web-Api via Http REST)
- \app\Models\Note.ts (Our UI model class we would be using as Type in our typescript)
- \app\systemjs.config.js
1. In our \app folder we add a typescript file named main.ts. Then in this file we type ng2 and we should see the Angular 2 code snippets as we installed from extension as in below image.
We select ng2-bootstrap template and the code will scaffold into Angular 2 bootstrap template. We do few updates to this file something like below.
import { enableProdMode } from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '@angular/http';
import { NotesListComponent } from './noteslistcomponent';
bootstrap(NotesListComponent, [HTTP_PROVIDERS])
.then(success => console.log('Bootstrap success'))
.catch(error => console.log(error));
2. Up next we created our component NotesListComponent in its own file noteslistcomponent.ts. This is the component which our main.ts class is importing above. We can use ng2-component template to scaffold this Component for us. @Component is an Angular 2 decorator. It takes Metadata as argument - which is used to describle how our component classes will be used by Angular 2.
import { Component, OnInit } from '@angular/core';
import { NotesService } from './Services/NotesService';
import { Note } from './Models/Note';
@Component({
moduleId: module.id,
selector: 'notes-list',
templateUrl: '/app/Views/noteslistcomponent.html',
providers:[NotesService]
})
export class NotesListComponent implements OnInit {
allnotes:Note[];
selectedNote:Note;
newNote:Note;
isUpdated:boolean;
constructor(private notesService:NotesService) { }
ngOnInit() {
this.notesService.getNotes().subscribe(lst=>this.allnotes=lst.json());
this.selectedNote = new Note('','','');;
this.newNote = new Note('','','');;
}
onSelect(note){
this.selectedNote=note;
}
onAdd(note){
if(note.Text.trim()==''){
return;
}
this.notesService.addNote(note).subscribe(rsp=>{
note.Id=this.trim(rsp.text(),'"');
this.allnotes.push(note);
let fresh=new Note('','','');
this.newNote = fresh;
});
}
onUpdate(note){
if(note.Id.trim()==''){
return;
}
this.notesService.updateNote(note.Id,note).subscribe(rsp=>{
console.log(rsp.text());
if (rsp.text()=='true')
{
let fresh=new Note('','','');
this.selectedNote = fresh;
}
});
}
onDelete(note){
if(note.Id.trim()==''){
return;
}
this.notesService.deleteNote(note.Id).subscribe(rsp=>{
console.log(rsp.text());
if (rsp.text()=='true') {
this.deleteItem(this.allnotes,note);
let fresh=new Note('','','');
this.selectedNote = fresh;
}
});
}
trim(str, chr) {
var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^'+chr+'+|'+chr+'+$', 'g');
return str.replace(rgxtrim, '');
}
deleteItem(arr:Note[],itm:Note){
for (var idx = 0; idx < arr.length; idx++) {
var elm = arr[idx];
if (elm.Id==itm.Id) {
arr.splice(idx,1);
}
}
}
isEquivalent(a, b) {
var bVal=JSON.stringify(a) === JSON.stringify(b);
return (bVal);
}
}
2.b
And here is the CRUD view \angdnx\app\Views\noteslistcomponent.html we are refering to in above component:-
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered">
<tr>
<td colspan="4">
Edit (Select an Item below first)
</td>
</tr>
<tr>
<th>Title</th>
<th>Text</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<tr>
<td><input class="form-control" placeholder="Title" type="text" [(ngModel)]="selectedNote.Title" /></td>
<td><textarea class="form-control" placeholder="Text" type="text" [(ngModel)]="selectedNote.Text"></textarea></td>
<td><input type="button" value="Update" (click)="onUpdate(selectedNote)"/></td>
<td><input type="button" value="Delete" (click)="onDelete(selectedNote)"/></td>
</tr>
</table>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered">
<tr>
<th>Title</th>
<th>Text(Click to Select)</th>
<th>Id(Click To Select)</th>
</tr>
<tr *ngFor="let note of allnotes">
<td class="col-sm-2" (click)="onSelect(note)">{{note.Title}}</td><td class="col-sm-8" (click)="onSelect(note)"> {{note.Text}}</td><td (click)="onSelect(note)">{{note.Id}}</td>
</tr>
</table>
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered">
<tr>
<th colspan="3">
Add
</th>
</tr>
<tr>
<th>Title</th>
<th>Text</th>
<th>(Add)</th>
</tr>
<tr>
<td>
<input class="form-control" placeholder="Title" type="text" [(ngModel)]="newNote.Title" />
</td>
<td>
<textarea class="form-control" placeholder="Text" type="text" [(ngModel)]="newNote.Text"></textarea>
</td>
<td>
<input type="button" value="add" (click)="onAdd(newNote)">
</td>
</tr>
</table>
</div>
</div>
3. Here is our \app\Services\NotesService.ts class which is reference above in NotesListComponent.ts:-
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import "rxjs/add/operator/map";
import { Note } from '../Models/Note';
@Injectable()
export class NotesService {
apiUrl:string;
constructor(private http:Http) {
this.apiUrl='/api/note';
}
getNotes(){
return this.http.get(this.apiUrl).map((res: Response) => res);
}
updateNote(id:string,note:Note){
let body = JSON.stringify(note);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.put(this.apiUrl+'/'+id,body, options).map((res:Response)=>res);
}
addNote(note:Note){
return this.http.post(this.apiUrl,JSON.stringify(note)).map((res:Response)=>res);
}
deleteNote(id:string){
return this.http.delete(this.apiUrl+'/'+id).map((res:Response)=>res);
}
}
4. And of course here is our simple UI Model class which we're using as type in above classes.
export class Note {
Id:string;
Title:string;
Text:string;
constructor(id:string,title:string,text:string) {
this.Id=id;
this.Title=title;
this.Text=text;
}
}
If our typescript is showing reference errors in VSCode, we add the following line to the top of or main.ts:-
This references the typings and we should immediately see the the typescript error markers disappear.
There's various commands listed in Angular 2 help page to transpile and play around our typescript files. We simply go to our project directory in Terminal and typed following:-
tsc -p .
We would see for each of our ts file there would be a transpiled js(and corresponding .map file) generated. If not, possibly you've missed installing npm typescipt/typings - please verify again.