Вы находитесь на странице: 1из 22

Angular: Getting Started

Angular is javasript framework


for client side apps, using HTML,CSS and JavaScript

Why Angular Framework ?


1)Expressive HTML
2)Data Binding
3)Modularity by design
4)Built In Backend integration

Why New Angular ?


Built for speed - faster rendering time
modern - uses latest javascirpt classes
simplified API
Enhance Productivity

Anatomy of Angular APP

Angular App = {Components + Service}

Component = {Template + Class(Properties & Methods) + Metadata}

Template is a View created with HTML


Class is the code supporting the view. Created in TypeScript
metadata -> additional info about component

Angular Modules :

Root Angular Module = {Component1 + Component2 + .......N}

GitHub Repository :
https://github.com/DeborahK/Angular-GettingStarted

Sample App Arc

Index.cshtml is associated with App Component

App Component is associated with below components


{
Welcome Component
Products List Component Star Component
Product Details Component
}

Product data service

JS Language Specification
ECMAScript(ES)

ES5
ES2015 -> must be transpiled to ES5

Select a Language
ES5 -> Runs in browser, no compile req
ES2015 -> lot of features but must be transpiled
TypeScript -> Open Source Language
Superset of JS,
Transpiles to plain JS
Strongly Typed(by TS type definition files (*.d.ts))
Class based object orientation

for more info check typescript playground

Select an Editor - Visual Studio Code

for more info refer pluralsight course "Visual Studio Code"

Setup Environment :
For Installing npm
Install Node from https://www.npmjs.com

Setup Angular App :

Download boiler plate code from


https://github.com/angular/quickstart

https://github.com/DeborahK/Angular-GettingStarted

Running an Angular App :

npm install in Integrated Terminal to install


all packages mentioned in package.json

"ng serve -o"


ng executes angular cli
cli command "serve" builds the app and starts the web server
-o opens the url in default browser

To start the App : npm start

Modules :

ES 2015 Modules -
are code files that import or export something

product.ts
export class Product{

product-list.ts
import {Product} from
'./product'

Angular Modules -
code files that organize the app into cohesive blocks
of functionality

Root Angular Module


{Component1, Component2,....N }
Component

Angular is Modular
import {Component} from '@angular/core';-> angular Library Module

Defining the Metadata


A component will become angular component when we define the Component Metadata.
Angular needs this metadata to instantiate the component, construct the view and
interact wit the component.

Decorator
It is a function that adds metadata to a class, members or method arguments.

Component is a decorator
{{ }} is for binding

@Component({
selector: 'pm-root' -> used in HTML
template:<h1>{{pagetitle}}</h1>
})

export class AppComponent


{
pagetitle:string = 'Acme Product Management System';
}

BootStrapping App Component


index.html contains main page of app.
it is often the only web page of the app.
hence called SPA.

In app.module.ts

@NgModule({
declarations:[AppComponent],
imports:[],
providers:[],
bootstrap:[AppComponent]

})

export class appmodule{}

Component CheckList :
Class -> Code
Decorator -> Metadata
Import what we need

Building a Template :

for bootstrap framework the below link will be useful


http://getbootstrap.com/
Add Products folder -> Add Product-list Component

Binding with Interpolation


{{}} is used for interpolation, it is one way binding from
class to template

Template
<h1>{{pageTitle}}</h1>

export class appcomponent


{
pageTitle: = 'Acme Product Management';
}

Add Logic using Directives


Custom Directives
using a component as directive
BuiltIn Directives
*ngIf, *ngFor (Structural Directives)

browser module exposes the *ngIf, *ngFor

using for of and for in


for in is for iterating index(itereates over properties of an object)

Template Checklist
Inline Template
Linked Template
Use component as directive

Interpolation Checklist
one way binding, uses curly braces

Strutural Directives
prefix with an *
*ngIf : evaluates true or false so an element is added or removed
*ngFor : define local variable with Let and use of

Data Binding and Pipes


Data Binding between DOM and Component

Interpolation
{{ }}

Property binding
<img [src]='product.imageurl'>

Event binding
showImage: boolean = false;
toggleImage() : void {
this.showImage = !this.showImage;
}
<button class='btn btn-primary' (click) = toggleImage()>
2 way binding
[(ngModel)] = 'listFilter'
[] is property binding, () is event binding
ngModel belongs to @angular/forms

Pipes(|)
transform bound properties before display
built in : date, number, decimal, currency, json, slice.
custom pipes

Checklist for Databinding


ngModel, Pipes

Defining Interfaces
ES5,ES2015 do not support interfaces
only TypeScript supports interfaces

In Component properties and methods are strongly typed


export class ProductListComponent
{
productList: string = 'Product List';
imageWidth: number = 50;
imageMargin: number = 2;

products: any[] should be changed to products: IProduct[]

toggleImage() : void {
}
}

Interface is to provide strong typing and better tooling support.

Encapsulating Component Style

style :

@Component({

styles: ['thead{color: #337AB7;}']


})

styleUrls :

@Component({

styles: ['./product-list.component.css']
})

Component Lifecycle & Lifecycle Hooks

Component Lifecycle :
Create -> Render -> Create and Render Childs -> process -> destroy

OnInit, OnChange, OnDestroy

import {OnInit} from '@angular/core'


export class ProductListComponent implements OnInit{
ngOnInit() : void {
console.log('In OnInit');
}
}

Build Custom Pipes


convert-to-spaces.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
name: 'ConvertToSpaces'
})

export class ConvertToSpaces implements PipeTransform{

transform(value:string, character:string) : string{

return value.replace(character, ' ');


}

Filtering a List
Angular team recommends placing the filtering and sorting logic in the
component itself.

In product-list.component.ts
_listFilter: string;
get listFilter() : string
{
return this._listFilter;
}
set listFilter(value: string)
{
this._listFilter = value;
this.filteredProducts = this.listFilter ?
this.performFilter(this.listFilter): this.products;
}

filteredProducts: IProduct[];

performFilter(filterBy: string): IProduct[]{


filterBy = filterBy.toLocaleLowerCase();
return this.products.filter((product : IProduct) =>
product.productName.toLocaleLowerCase().indexOf(filterBy) != -1);
}

In product-list.component.html
*ngFor let product of filteredProducts;

Building Nested Components

Nested Component -> {Template + Class}

Nested Component is placed within the Template of


Parent or Container Component.

Nested Component receives inputs from parent using property binding


and gives output back to parent using events.

In product-list.component.html
change <td>{{product.starRating}}</td>
to
<td><pm-star></pm-star></td>

Declare in app.module.ts

Passing data to Nested Component :

To provide input to nested component use @Input


export class StarComponent implements OnChanges
{
@Input() rating: number;

In product-list.component.html
<td><pm-star [rating]='product.starRating'></pm-star></td>

Passing data from Nested Component to Parent :

export class StarComponent implements OnChanges


{
@Output() ratingClicked: EventEmitter<string> = new EventEmitter<string>();

this.ratingClicked.emit('The Rating is clicked');

In product-list.component.html
<td><pm-star (ratingClicked)='OnRatingClicked($event)'></pm-star></td>

Services and Dependency Injection

Service is a class used for features independent from any particular component.
encapsulate external interactions.

Angular Injector maintains a singleton instance of services


ex: log, math, svc etc

Angular Injector injects a service instance when component


is instantiated.Dependency Injection is used.

Service
export class myservice{}

Component
constructor(private _myservice){}

Building a Service
@Injectable()

export class ProductService{


getProducts(): IProduct[]{
return;
}
}

Register a Service
Registered in Component
Injectable to component and its children
Registered in Angular Module
Injectable to anywhere in app

In app.component.ts

Injecting a service
A singleton Instance of the service is injected into the component through
the component constructor.

constructor(private _productService : ProductService)

ngOnInit() : void {
this.products = this._productService.getProducts();
}

Retrive data using HTTP


Helps Manage asynchronous data
Treat events as a collection(an array whose items arrive asynchronously over time)
Observables are used from third party library called Reactive Extensions(RxJS)

A method can subcribe to an observable and receive notifications for asynchronous


data.

Sending an HTTP Request

import { HttpClient } from "@angular/common/http";


import { Observable } from "rxjs/Observable";

@Injectable()

export class ProductService{


private _productUrl: string = './api/products/products.json';
constructor(private _http: HttpClient){
}
getProducts(): Observable<IProduct[]>{
return this._http.get<IProduct[]>(this._productUrl);
}
}

Subscribe to an observable

In Service
getProducts(): Observable<IProduct[]>{
return this._http.get<IProduct[]>(this._productUrl);
}

In Component

ngOnInit() : void {
this._productService.getProducts()
.subscribe(products => {this.products = products;
this.filteredProducts = this.products;},
error => this.errorMessage = <any>error);

Navigation and Routing in angular

when the browsers url changes, angular looks for route definition matching the
path segment.then, angular loads the ProductListComponent Template.
{path: 'products', component: ProductListComponent}

localhost:3000/products

Menu
Home Product List <a routerlink="/products">Product List</a>

Configuring Routes

RouterModule.forRoot([
{path: 'products', component: ProductListComponent},
{path: 'products/:id', component: ProductDetailComponent},
{path: 'welcome', component: WelcomeComponent},
{path: '', redirectTo: 'welcome', pathmatch: 'full'},
{path: '**', component: PageNotFoundComponent}
])

order of the route also top to bottom.

Tying Routes to Actions

Use routerLink Attribute in <a> tag of the menu.

<a [routerLink]="['/welcome']">

<ul class='nav navbar-nav'>


<li><a>Home</a></li>
<li><a>Product List</a></li>
</ul>
<router-outlet></router-outlet> -> It is used to display the
routed view.

Passing parameters to route

constructor(private _route: ActivatedRoute){}


ngOnInit() {

let id = this._route.snapshot.paramMap.get('id');

this.pageTitle += `: ${ id }`;

this.product = {
"productId": parseInt(id)}
}
Navigate to a route from code
constructor(private _router: Router) { }
onBack(): void {
this._router.navigate(['products']);

Protect route with guards

Add a service called product guard service


ng g s products/product-guard.service -m app.module

export class ProductGuardService implements CanActivate {

constructor(private _router : Router) { }

canActivate(route: ActivatedRouteSnapshot): boolean{

let id = route.url[1].path;

if(isNaN(parseInt(id)) || parseInt(id) < 1){

alert("Invalid Product Id");

this._router.navigate(['/products']);

return false;

return true;

}
}

Angular Modules
A class with NgModule decorator. Organizes our code into blocks.
Extends app with capabilities from external libraries.

For Example :
1)app module imports the system modules we need
BrowserModule, FormsModule, RouterModule etc.

2)declares the components and pipes we create.

3)It registers the service provider for product detail guard

4)It bootstraps the app with the component AppComponent


5)Angular module provides template resolution environment.

Bootstrap Array
bootstrap: [AppComponent]
a)every app must bootstrap atleast one component, the root app component.
b)Bootstrap Array should only be used in root application module,AppModule.
Declarations Array
a)Every component, directive, pipe we create must belong to one and only one
angular module.
b)only declare components, directives and pipes
c)never redeclare from another module.

Exports Array
exports: []
a)export any component, directive or pipe.
b)never export a service

Imports Array
imports: []
we can import an angular module, 3rd party module etc

providers Array
a)providers:[] allows us to register services at module level
b)service added to the providers array is registered at root of the app.
c)don't add services to providers array of shared module.instead build a
module for services and import into appmodule.
d)Routing guards must be added to providers array of an angular module.

Feature Module

A Module has to be created based on Feature sets.Move Products to a


seperate module.
ng g m products/product --flat -m app.module

Shared Module
Commonly used modules can be kept in shared modules and exported.

ng g m shared/shared --flat -m products/product.module

browsermodule: every browser app should import.it registers critical


app service providers.*ngIF and *ngFor are available

Angular CLI
A command line interface for angular.
purpose is to build an angular app, execute the app, run tests and
deployment.
npm install -g @angular/cli

ng new Hello-World
Creates a New App

In The Project folder the below are also found


assets -> Images etc
environments -> setup the build environment for dev and production
Main.ts -> bootstraps the app
polyfills aids to support evergreen browsers and classic browsers
styles.css is to set global styles.
test.ts -> Setsup testing
tsconfig files are for typescript configurations
typings -> provides typings for typescript

ng serve
used to run the app
ng generate
used to generate a component, class, service etc

ng test and ng e2e are used for unit tests and end to end tests.

ng build -> to deploy the app

ng build --help -> it will give all associated commands

Angular Intermediate Fundamentals

https://github.com/jmcooper/angular-fundamentals-files

rm -rf node_modules

How Angular App is BootStrapped ?

main.ts file is loaded when app first loads.


In main.ts file
bootstrapModule(AppModule)
The above is done.

In app.module.ts
bootstrap: [AppComponent]

In app.component.ts
selector: 'app-root'

Access Static Files


a)paths are relative to index.html file
b)To make static files available include the folder name in angular-cli.json
under "assets":[].
c) use "styles":[] and "scripts":[] to load styles and scripts along with
your app
can add bootstrap styles and script files to the above section.

Components
a)template url is relative to component.

Pass data to child component

In Child Component :
export class EventThumbnailComponent {
@Input() event:any;
}

In Parent Component :
<eventthumbnail [event]="event1" ></eventthumbnail>
export class EventListComponent {
event1 = {}
}
pass data from child component to Parent component

In Child Component :
export class EventThumbnailComponent {
@Output() eventclick = new EventEmitter();

onButtonClick(): void{
this.eventclick.emit("foo");
}
}

In Parent Component :

<eventthumbnail (eventclick) = "handleEventClicked($event)" ></eventthumbnail>


export class EventListComponent {

handleEventClicked(data){
console.log('received:', data);
}
}

Using Template Variable

In Parent Component
<eventthumbnail #thumbnail ></eventthumbnail>
<p>{{thumbnail.someproperty}}</p>

In Child Component :
export class EventThumbnailComponent {

someproperty: any = "some value";


}

Angular CSS Encapsulation


Global CSS applies to the site. If style is chosen at component level
then it applies only to that component not even to the childs.

Adding a site header


Menu is added as a component to AppComponent
template: `<nav-bar></nav-bar>
<events-list></events-list>`

Interpolation, Property Binding & Event Binding

template:`<h2>{{user.name}}</h2>
<image [src]= "user.imageUrl"></image>
<button (click)="doSomething()"></button>`

export class AComponent


{
user = {name:'tom', imageurl:''}
doSomething(): void{}
}

Repeating data using *ngFor


In Parent Component :
<eventthumbnail *ngFor="let event of events" [event]="event1" ></eventthumbnail>
export class EventListComponent {
events = {}
}

Handling null using safe navigation operator


template:`<h2>{{event?.name}}</h2>`
? is the safe navigation operator.

Hide & show Elements


using *ngIf :
template:`
<div *ngIf="event?.name">
<h2>{{event?.name}}</h2>
</div>`

Note : element will not be rendered in the DOM.

using hidden :
template:`
<div [hidden]="!event?.name">
<h2>{{event?.name}}</h2>
</div>`

Note : element will be rendered in the DOMbut hidden.

using ngSwitch
<div [ngSwitch]="event?.time">
<span *ngSwitchCase="'8:00 am'"> Early Start</span>
<span *ngSwitchCase="'10:00 am'"> Early Start</span>
<span *ngSwitchDefault> Normal Start</span>
</div>

Styles using ngClass


<div [ngClass]="GetStyleClasses" [ngSwitch]="event?.time">
styles:[`.green{color:#003300} .bold{font-weight:bold;}`]

GetStyleClasses(){
if(this.event && this.event.time === '8:00 am')
return 'green bold'
return ''
}

Styles using ngStyle


<div [ngStyle]="GetEarlyStyle" [ngSwitch]="event?.time">

GetEarlyStyle(): any{
if(this.event && this.event.time === '8:00 am')
return {color:'#003300', 'font-weight': 'bold'}
return {}
}

Services
Adding a 3rd Party Service

npm install toastr --save


In angular-cli.json add in styles and scripts
"../node_modules/toastr/build/toastr.min.css"
"../node_modules/toastr/build/toastr.min.js"
Create a Service "ToastrService"
import { Injectable } from '@angular/core'
declare let toastr:any
@Injectable()
export class ToastrService{
success(message:string, title?: string){
toastr.success(message, title)
}
}

Routing and Navigation of Pages

1)In appcomponent :
template:
`<router-outlet></router-outlet>`

2)create a file route.ts add all route definitions


export const appRoutes:Routes =[
{path: 'events', component: EventsListComponent},
{path: 'events/:id', component: EventDetailsComponent}
{path: '', redirectTo: '/events', pathMatch:'full'}

3)In App Module load the routes using routerModule


imports:[RouterModule.forRoot(appRoutes)]
4)In Index.html add base Tag for routing <base href="/">

Access Route Parameters


export class EventDetailsComponent{
constructor(private route:ActivatedRoute){}
ngOnInit(){
let id = this.route.snapshot.params['id']
}
}

Linking to Routes
In HTML Template
<div [routerLink]="['/events', event.id]">
</div>

Navigating from Code


In the component inject the router and call navigate.

export class CreateEventComponent{


constructor(private router: Router){}
cancel() {
this.router.navigate(['/events'])
}
}

Guarding against route Activation


Create a Provider "EventRouteActivator" :

export class EventRouteActivator implements CanActivate {


constructor(private router: Router){}
CanActivate(route:ActivatedRouteSnapShot){
}
}

export const appRoutes:Routes =[


{path: 'events', component: EventsListComponent},
{path: 'events/:id', component: EventDetailsComponent,
canActivate: [EventRouteActivator]},
{path: '', redirectTo: '/events', pathMatch:'full'}
]

Guarding against route DeActivation ?

Pre-Loading Data for Components Using Resolver


Add a Service "EventListResolver" :

export class EventListResolver implements Resolve<any> {


constructor(private eventservice:EventService){}
resolve(){
return this.eventservice.getEvents().map(events => events)
}
}

In routes.ts :

export const appRoutes:Routes =[


{path: 'events', component: EventsListComponent, resolve:
{events1:EventListResolver}},
]

In Component.ts

constructor(private route: ActivatedRoute){}


ngOnInit(){
this.events = this.route.snapshot.data['events1']
}

Styling Active Links

<a [routerLink]="['/events']" routerLinkActive="active"


[routerLinkActiveOptions]="{exact:true}">All Events</a>

Lazily Loading Feature Modules


Large Sites can be broken into smaller sections.
Create a component called profile.component.ts
Create a feature Module called user.module.ts

imports:[
CommonModule,
RouterModule.forChild(userroutes)
]
the above are different from app module.

In Main Module Route config :

export const appRoutes:Routes =[


{path:'user', LoadChildren:'app/user/user.module#UserModule'}
]

The routes will starting from /user/profile

In HTML : <a [routerLink]="['user/profile']">Welcome John"</a>

user/profile will be lazy loaded.

Angular Forms and Validation ?

Reusing Components with Content Projection

Creating component to implement collapsible content


In collapsible-well Component.ts
@Component({
selector: 'collapsible-well'
template:`<div (click)="togglecontent()">
<h4>{{title}}</h4>
<ng-content *ngIf="visible"></ng-content>
</div>`
})

export class CollapsibleWellComponent{


@Input() title: string;
visible: boolean = true;
togglecontent() {
this.visible = !this.visible;
}
}

In a given component.ts

<collapsible-well [title]="session.name">
//html content
</collapsible-well>

MultiSlot Content Projection

--------------------------------------------------------------------
2 types of forms technologies

1)Template Driven Forms


use a component's template
Unit Test against DOM

2)Reactive Forms
use a component's template
create a form model in typescript(it must be in sync with template)
Unit Test Against Form Model
Validation in Form Model

Angular Versions :
RC 4 and earlier -> old forms API bootstrap a component
RC5 to 2.0 -> New Forms API bootstraps a NgModule

In app.module.ts -> "FormsModule" should be imported.

A simple form and ngForm

<h3>Angular 2 Forms</h3>
<form #form="ngForm">
<input type="text" placeholder="Name" name="name" ngModel>
<button type="submit">Ok</button>
</form>

{{ form.pristine }}

Shutting off browser validation

<form #form="ngForm" novalidate >


<input type="text" required placeholder="Name" name="name" ngModel>
<button type="submit">Ok</button>
</form>

Adding Bootstrap

http://getbootstrap.com/docs/4.1/getting-started/introduction/

Copy the CSS and paste it in index.html


<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css"
integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
crossorigin="anonymous">

In home.component.html

<div class="container">
<h3>Angular 2 Forms</h3>
<form #form="ngForm" novalidate>
<div class="form-group">
<label> First Name</label>
<input type="text" class="form-control" required name="firstname"
ngModel>
</div>
<button class="btn btn-primary" type="submit">Ok</button>
</form>
</div>

Here create a div class called container, change button type to btn bth-primary
input type of class form-control.

Note : Each control should have a name and ngModel should be specified
for angular to access or validate it.

Summary :
ngForm, ngModel directives
NoValidate
BootStrap Styling
Checkbox, radiobutton, select-options using *ngFor
Browser Inconsistencies for differnet controls

Data Binding in Angular Forms

ngModel is directive placed on forms fields for controlling.

//No Binding but angular builds an obj based on first name


<input name="firstname" ngModel>

//One Way Binding : Property Binding


<input name="firstname" [ngModel]="firstname">

//2 Way Binding : Property Binding + Event Binding


<input name="firstname" [(ngModel)]="firstname">

Binding to Model

In HTML
<input type="text" class="form-control" name="firstname" [ngModel] =
"model.firstName"
(ngModelChange) = "model.firstName=$event">

In Component.ts
model = new Employee("Darla", "Smith");

calling a method in place of binding

<input type="text" class="form-control" name="firstname" [ngModel] =


"model.firstName"
(ngModelChange)="firstNameToUpperCase($event)">

In Component.ts
firstNameToUpperCase(value: string){
}

CSS Classes for Validation

The 3 set of classes handled by angular :

ng-untouched
ng-touched -> when a field loses focus

ng-pristine
ng-dirty

ng-valid
ng-invalid

The associated ngModel properties are


untouched
touched
pristine
dirty
valid
invalid

Showing Error Messages


<input #firstName="ngModel" required type="text">
<div *ngIf="firstName.invalid && firstName.touched" class="alert alert-danger">
First Name is Required
</div>

check in caniuse.com if these attributes can be used

required, pattern(), maxlength, minlength,

Validating Select Control

Form Level Validation


Properties are available at form level also
untouched
touched
pristine
dirty
valid
invalid

Posting to the service


In Angular Project create a service for http.
@angular/http allows us to use HTTP protocol

Inject the Service to home component.

constructor(private formposter : FormPoster){}

submitForm(form: NgForm){
this.formposter.postEmployeeForm(this.model).subscribe(
data => console.log('success', data),
err => console.log('error', err)
)
}

In HTML Template :
<form #form="ngForm" (submit)="submitForm(form)" novalidate>

In Service

return this.http.post('http://localhost:3100/postemployee', body, options)


.map(this.extractData).catch(this.handleError);

Get Data from the service


In Component within constructor

this.formposter.getLanguages().subscribe(
data => this.languages = data.languages,
err => console.log('error', err)
)
In service
getLanguages() : Observable<any>{
return this.http.get('http://localhost:3100/get-languages')
.map(this.extractLanguages).catch(this.handleError);
}

-----------------------------------------------------------------------

Angular JS Forms and MVC5 by mark zamoyta


shows how angular js forms can post to mvc server also.

How to setup a Node Server ?

create a folder and run npm init

setup the default and proceed

npm install --save formidable -> it will help us process forms

var http = require('http');


var formidable = require("formidable");
var util = require('util');

var server = http.createServer(function(req, res)) {


res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-
Type, Accept');

if(req.method.toLowerCase() == 'post'){
processForm(req, res);
return;
}

if(req.method.toLowerCase() == 'get'){
var data = {data:{languages:['English', 'Spanish', 'German', 'Other']}};
var responseData = JSON.stringify(data);
res.end(responseData);
console.log("get: ", responseData);
return;
}

res.end();
});

function processForm(req, res){


var form = new formidable.IncomingForm();

form.parse(req, function(err, fields){


res.writeHead(200, {
'content-type': 'text/plain'
});

var data = JSON.stringify({


fields: fields
});
res.end(data);
console.log('posted fileds:\n');
console.log(data);
});

};

var port = 3100;


server.listen(port);
console.log("server listening on port " + port);

Start the server using the command


node server.js

can we send addtional data from node server in response?

Yes, add fields.id = "some value";

Вам также может понравиться