angular, rest and u2 - the rocket software blog · pdf fileangular, rest and u2 blog post 2 ....

37
Brian Leach Consulting Limited http://www.brianleach.co.uk Angular, REST and U2 Blog Post 2

Upload: duonghanh

Post on 24-Mar-2018

217 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Brian Leach Consulting Limited

http://www.brianleach.co.uk

Angular, REST and U2

Blog Post 2

Page 2: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 2 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Contents

Introduction ....................................................................................................................... 3

Prerequisites ...................................................................................................................... 3

What is REST? .................................................................................................................... 4

Defining our First RESTful Service ....................................................................................... 5

Create a REST Server ....................................................................................................... 6

Create a Resource Folder ................................................................................................ 6

Create a Data Resource ................................................................................................... 7

Testing the Data Resource............................................................................................... 9

Creating your First Angular Component............................................................................ 10

Creating the Model ....................................................................................................... 10

Creating a Service ......................................................................................................... 11

Creating the Component ............................................................................................... 12

Updating the Routing .................................................................................................... 13

Creating the Component UI........................................................................................... 14

Running the Component ............................................................................................... 15

Adding Searching ............................................................................................................. 16

Adding a Selection Clause ............................................................................................. 16

Fetching a Value from the UI ......................................................................................... 17

Adding Pagination ............................................................................................................ 18

Connecting Components .................................................................................................. 21

Creating the Data Resource ........................................................................................... 21

Creating the TypeScript Model ...................................................................................... 21

Updating the Service ..................................................................................................... 22

Making the Connection ................................................................................................. 23

Creating a Maintenance Form .......................................................................................... 25

Creating the HTML Form ............................................................................................... 25

Adding Validation .......................................................................................................... 27

Types of Validation ....................................................................................................... 28

Putting Updates ............................................................................................................... 29

Calling a Subroutine ......................................................................................................... 32

Mapping the Subroutine Parameters ............................................................................ 34

Next Steps ........................................................................................................................ 37

Page 3: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 3 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Introduction

In the first post of this series, we looked at Angular - the Single Page Application framework

from Google - from the perspective of the web client. We delved into the template syntax

used to specify Angular components and modules, the routing and the data binding. We

introduced TypeScript, the highly typed and modular meta-language that transpiles to

JavaScript. We created a working sample project using Microsoft Visual Studio 2017 and

ASP.NET WebAPI. We even looked briefly at the http module and RxJS Observables and

Promises, the mechanisms required for bringing RESTful data into our project.

After all that scene-setting in the first post, we are ready to start building our own Angular

components and to start connecting these to our U2 systems. In this post, we will be using the

built-in U2 RESTful Web Services to provide and consume information, running queries and

calling stored procedures.

Prerequisites

Before we begin, there are some additional assets you will need to get up and running.

First and foremost, you will need a copy of UniVerse. All of this will work equally with UniData,

but the examples here will be UniVerse driven. If you do not have easy access to a copy on

your PC, you can download the free limited UniVerse Personal Edition from Rocket by visiting

http://www.rocketsoftware.com/u2 and clicking on the ‘Try it now’ button.

You will also need to install the U2 RESTful Web Services Developer from the Rocket U2

DBTools package, available from the same location as the UniVerse Personal Edition above.

We will be using the Book Store demonstration database that forms the backbone to the

Incubator Project, an open source project sponsored by Brian Leach Consulting for the

MultiValue World user group and available at:

http://www.mvdeveloper.com/public/files/u2_books_universe.zip

Page 4: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 4 Blog Post 2

Brian Leach Consulting Limited Version 1.0

What is REST?

REST (REpresentative State Transfer) is a series of protocols built around HTTP, XML and JSON.

It is better described as a set of conventions: an agreement to use these already mature

technologies in a more-or-less standard way. REST leans on the four primary HTTP verbs - GET,

PUT, POST and DELETE - and uses these in a predictable way. REST therefore needs no special

services on the client and HTTP is well handled through the layers that make up any modern

infrastructure: any browser can issue HTTP requests and support for JSON has been part of

the currency of the web, albeit in different guises, for over a decade.

REST describes a uniform approach to accessing resources through URIs. A URI might

represent a data source, but REST makes no assumptions about what that source might be or

how it should behave. The only requirements are that it should respect the HTTP verbs and

that any data provided must be capable of being represented in JSON, XML or HTTP format.

There is no requirement for normalization and so this fits with the modern world of web

development and the rise of JSON-oriented NoSQL and document oriented databases as

today’s platforms of choice, freeing developers from the constrictions imposed by the legacy

SQL model and the need to navigate proprietary protocols.

That is especially good news for MultiValue sites, since both XML and JSON happily

encapsulate nested entities and all the complexity involved in MultiValue data, and so it

means we can expose our native model without the need to dynamically normalize our files,

avoiding the overheads associated with using relational protocols such as ODBC or ADO.NET.

And because REST also makes no differential between URIs, tools like the Rocket U2 RESTful

Web Services can equally surface out data files and subroutines as end points.

REST defines a specific meaning for each HTTP verb:

GET List a collection or Fetch a specific element

PUT Replace a collection or Create/Update/Replace a specific element

POST Create a new entry in a collection

DELETE Delete a collection or delete a specific element

PATCH Update an element (will be supported by Rocket in the future)

In CRUD terms these can be seen as roughly equivalent to:

GET Read

PUT Update/Replace

POST Insert

DELETE Delete

PATCH Update

Because this is driven by convention, not all implementations necessarily obey all these rules.

Page 5: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 5 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Defining our First RESTful Service

For our first service, we are going to expose one of the data files in the u2_books account that

forms part of the Incubator Project database installed above. This represents a bookstore

containing regular and audio publications. We will use a RESTful service to retrieve two sets

of book information directly from a file: a summary view that will form a listing component in

Angular, and a detail view that we will use later down the track to create a maintenance

component.

Start the U2 RESTFul Web Services Developer (henceforth RWSD), and once it has loaded, right

click on ‘Servers’ in the top left panel and select ‘New Server’. If you have installed UniVerse

Personal Edition, enter localuv as the server name and localhost for the connection. If not you

will need to enter the name of your remote server.

Next, right click on the localuv entry and select ‘Connect’: this uses UniObjects (as UOJ) to

connect, so you will need to supply your database user name and password: for Personal

Edition, these are your Windows credentials.

This opens a list of accounts drawn from the UV.ACCOUNT file in the uv home account. If your

u2_books account is not there don’t worry, you can add it: right click the Accounts folder and

select ‘New Account’. You can enter the path to an existing account and it will just add the

UV.ACCOUNT entry. If you prefer you can go to TCL in the uv account and type:

INSERT INTO UV.ACCOUNT(@ID,PATH) VALUES (‘u2_books’,’path_to_u2_books’);

If all went well, you should now be able to open the u2_books folder in RWSD and see a list of

all the files (including Q pointers) in that account.

Page 6: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 6 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Create a REST Server

Before we can expose of any of the files for use, we need to create a REST server. This will be

the gateway through which we can access the various data and subroutine resources we will

define in this account. In the lower left panel, right click the REST Servers icon and select ‘New

REST Server’. Here you get to define the location and connection details for the server:

The RWSD will fill in the URL with your machine name and select a port number above 9190.

If you do not have a connection pooling licence, or are using Personal Edition, make sure to

uncheck the Connection Pooling option.

Create a Resource Folder

We first want to expose the U2_BOOKS file. RWSD is sometimes less than intuitive: to do this,

drag the U2_BOOKS from the U2_Resource panel above and drop it onto the u2_book_server

entry. This will ask if you want to create a resource folder: say Yes to the prompt. The resource

folder binds together services from the same account, and holds the login credentials that the

server will need to access that account.

Page 7: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 7 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Note that you will need to use a service account with a non-expiring password if you deploy

these for real. Use the Test Database Connection button to check you have entered the details

correctly before you continue.

Create a Data Resource

Now the resource folder has been created, you can add the Data Resource that will provide

access to the U2_BOOKS file. This presents you with a list of the fields, including any virtual

fields, that you want to make available. This is contextual - you can create multiple resources

based on the same file, so you do not need to map every field to cater for every possible use

as part of the same resource.

We will start with only a summary view suitable for a listing. The U2_BOOKS file holds details

on the publications sold by our demonstration bookstore, and so we will select the ID, TITLE,

AUTHOR_NAME, ISBN, SALE_PRICE and MEDIA fields to identify these.

Page 8: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 8 Blog Post 2

Brian Leach Consulting Limited Version 1.0

On the next page we get to name the resource elements. Change the Resource Name to

U2_book_summary and the fields as follows: title, ISBN, salePrice, media, id, authorName.

That’s it - you have created your first Data Resource. Let’s see this in action.

Page 9: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 9 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Testing the Data Resource

You will notice that the u2_book_server has a red square over the icon: this shows that this

RESTful server is currently stopped. You cannot change the properties of a server or add

resources to it whilst it is running.

Right click on the icon and select ‘Start REST Server’. The icon changes to show a green overlay.

If not, you will need to check the U2 REST Server Log panel to see why the server could not

start (did you uncheck the Connection Pooling option?).

The easiest way to test the resource is from within the RWSD itself. Double click on the

U2_book_summary entry under Data Resources (consistency would be a virtue) and this

displays the results of the call:

This shows the first 10 U2_BOOKS records in a suitable JSON format under the container name

U2_book_summary.

We will investigate some of the options available for querying later but for now you are ready

to create your first Angular component to display these.

Page 10: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 10 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Creating your First Angular Component

In the first post, you created a new project in Visual Studio 2017 using the SPA Template. This

included several sample components and a WebAPI base that we will be using in the next post.

For now, we are going to add our components into this project. You can clean up the sample

components later at your leisure.

The FetchDataComponent that we investigated in the first post, demonstrates how to call a

RESTful service to fetch and display data. We will be extending what we learned from this just

a little for our book list summary.

Creating the Model

To consume RESTful data, we first must define a matching class or interface that Angular can

use to map the JSON content. In the sample project the interface definition for the

WeatherForecast was held inside the FetchDataComponent component, but that scheme

effectively binds it to that one resource. A better option is to place it in its own model directory

so it can be more easily reused.

The Angular side of the sample web application is held in the ClientApp\app folder. Right click

in there and add a new folder called models. Right click on that in turn and select ‘New Item’.

You will need to add a new TypeScript file to define this model. You will find this under Web

in the ASP.NET Core section of the Add New Item dialog:

Our summary model will be simple, nothing more than a field map for the data returned from

our resource, so we can use an interface. Add the following TypeScript definition to your

bookSummary.model.ts file:

Page 11: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 11 Blog Post 2

Brian Leach Consulting Limited Version 1.0

export interface BookSummary { id: string; title: string; authorName: string; ISBN: string; salePrice: number; media: string; }

Creating a Service

In the first post, we learned about Angular Components and Modules. These form the major

blocks in an Angular application, but there are other tools you will need to create a working

real world solution. One such tool is a Service.

A service brings together a set of functionality and properties that are not bound to a single

component. Services are typically used for handling data, including RESTful calls, where that

data will be shared between a set of components: services thus provide the glue between

components. We will be needing that to bridge between our first two components: our listing

will identify candidate books and lead directly to our maintenance component to edit them.

Add a new services folder under the ClientApp\app folder, then add into that a new TypeScript

file called booklist.service.ts. Services have no visible interface so you won’t need an HTML

page as well.

Here is the new service definition in full:

import { Injectable, Inject } from '@angular/core'; import { HttpModule, Http } from '@angular/http'; import { BookSummary } from '../models/bookSummary.model'; import { Observable } from 'rxjs/Observable'; @Injectable() export class BookListService { books: BookSummary[]; editing: boolean; constructor(private _http: Http, @Inject('REST_URL') private restUrl:string) { } getBooksFromREST(searchTerm: string) { this._http.get(this.restUrl + "/U2_book_summary").subscribe( result => {this.books = result.json().U2_book_summary as BookSummary[]; }); } }

Page 12: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 12 Blog Post 2

Brian Leach Consulting Limited Version 1.0

You may notice the close resemblance this bears to the FetchDataComponent we examined

in part 1.

I have added an Injectable for the REST_URL so this can be stored once against the application

module in exactly the same way the FetchDataComponent injects the ORIGIN_URL, rather

than having to repeat it for every RESTful call. In order that Angular will inject this on demand,

this needs to be added to the application module in the app.module.client.ts file, substituting

the resource path for your U2 REST Server:

providers: [ { provide: 'ORIGIN_URL', useValue: location.origin }, { provide: 'REST_URL', useValue: 'http://WORKVM:9193/u2_books'} ]

Creating the Component

We have now completed the data plumbing ready for adding our book list component. This

will present a table with the rows fetched from the booklist service. We can use the Bootstrap

styling to make it look a little prettier.

We will follow the same conventions as those used by the sample components, so add a folder

under components named bookList and a new TypeScript file within that called

booklist.component.ts.

The work of fetching the data has been delegated to the booklist service, so the component

itself is suitably simple: we just need to add BookListService to the list of imports and to the

providers property of the component metadata to make sure Angular can find it.

Here is the template definition for the listing component:

import { Component, OnInit, Injectable, Input } from '@angular/core'; import { BookListService } from '../../services/booklist.service'; import { BookSummary } from '../../models/bookSummary.model'; @Component({ providers: [BookListService], templateUrl:'./booklist.component.html' }) export class BookListComponent { constructor(public bookListService: BookListService) { bookListService.getBooksFromREST(''); } }

Page 13: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 13 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Updating the Routing

The project sets up the routing to create each of the sample components as we saw in the

previous post, so we will need to add our new component into this routing scheme. We need

to tell the module how to create the component and we need to add it to the routing table.

For this you need to look into app.module.shared.ts.

First, import the component you just created:

import { BookListComponent } from './components/bookList/booklist.component';

Next, update the declarations on the module so Angular will create the component on

demand:

declarations: [ AppComponent, NavMenuComponent, CounterComponent, FetchDataComponent, HomeComponent, BookListComponent

Now you can add the following line to the routing table:

{ path: 'book-list', component: BookListComponent },

That’s all we need from the Angular perspective to create our component, but we will still

need to add an entry into the menus to let us select it. Copy and paste the last entry on the

navmenu.component.html and change it to show our list:

<li [routerLinkActive]="['link-active']"> <a [routerLink]="['/book-list']"> <span class='glyphicon glyphicon-th-list'></span> Book List </a> </li>

This will create the routing entry book-list when it is selected.

Page 14: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 14 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Creating the Component UI

Nearly there - the final piece is to just add the UI to display the content. Add an html file to

the booklist component folder and name it booklist.component.html. This will hold the UI

snippet for our listing component using Angular interpolation to bind the content. We will also

create the Edit button for each row so we can use that later.

Note the use of the *ngFor directive we met in the first post to run through each row.

<div class="container"> <div class="row"> <div class="col-md-10 col-md-offset-1"> <div class="panel panel-default panel-table"> <div class="panel-heading"> <div class="row"> <div class="col col-xs-6"> <h3 class="panel-title">Book Listing</h3> </div> </div> </div> <div class="panel-body"> <table class="table table-striped table-bordered table-list"> <thead> <tr> <th></th> <th>Id</th> <th>Title</th> <th>Author Name</th> <th>ISBN</th> </tr> </thead> <tbody> <tr *ngFor="let book of bookListService.books"> <td> <button (click)="onEdit(book)">Edit</button> </td> <td>{{book.id}}</td> <td>{{book.title}}</td> <td>{{book.authorName}}</td> <td>{{book.ISBN}}</td> </tr> </tbody> </table> </div> <div class="panel-footer"> </div> </div> </div> </div> </div>

Page 15: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 15 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Running the Component

Now before we run the component, it’s worth taking stock of where we are.

We needed to add a lot of things for Angular to work its magic. This is normal and is the flip-

side of using such a powerful toolkit. Just in case all those steps have left you confused, here

is what you have created:

The Navigation Menu now has a button to show the Book List.

The button will set the address to /book_list

The module will route this address and create the BookListComponent.

The component will receive an instance of the BookList service as a provider.

The service will make a call back to the U2 RESTful server using http.

The U2 RESTful server will query the U2_BOOKS file.

The results will be converted into an array of BookSummary objects.

Angular will bind the array to the HTML table.

If you followed all steps correctly (and remember to run your RESTful service), you can now

run your project and select the Book List from the menu. This will display the list of titles as

below.

It is worth keeping a pad and paper to jot down the pieces you need before adding any Angular

component, otherwise you may forget a step and Angular is not forgiving.

Page 16: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 16 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Adding Searching

Returning a whole data set consisting of every record in a file is not a suitable strategy for

most real-world situations, so we need to add some filtering and pagination to our listing.

Additionally, the list is not sorted, so the order of the records is not helpful.

Adding a Selection Clause

The U2 RESTful Web Services support several options for refining the list of records returned.

These are all supplied as parameters on the request. First, let us change the sort order so it

follows the IDs:

http://myServer:9131/u2_book_service/U2_book_summary?sort=BY ID

The sort order is specified using the sort QueryString parameter in the same format as

RetrieVe or UniQuery. You can use multiple BY and BY.DSND clauses.

Selections are also handled similarly to the native enquiry languages. You can create a search

against any field or combination of fields as you would for a regular query by adding a select

parameter:

select=DEPT=JUNIOR AND TITLE LIKE …Potter…

Note that this will need to be URL encoded if it contains special characters such as quotation

marks.

We will use this to add a simple selection to our listing. This will do a partial search on the title

and author name to filter the books returned. Did you notice that in the BookList Service we

already added a search term to the getBooksFromREST() method? We can now implement

that in our request:

getBooksFromREST(searchTerm: string) { var uri = this.restUrl + "/U2_book_summary?sort=BY ID"; if (searchTerm) { uri = uri + '&select=TITLE LIKE "...' + searchTerm + '..." OR AUTHOR_NAME LIKE "...' + searchTerm + '..."'; } this._http.get(uri).subscribe( result => {this.books = result.json().U2_book_summary as BookSummary[]; }); }

Page 17: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 17 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Fetching a Value from the UI

We can apply a search term to our RESTful request, but where will it come from? It would be

nice to add a search box to our list component, and have the content of that box automatically

passed into the book service to fetch the matching titles.

Fortunately, we have already done all the hard work in setting up the component and service

definitions, so adding a feature like this is relatively trivial.

First, we need a means of capturing a value typed into the UI - here being our search box - so

we can use it from the backing component class. For this, the easiest way is to bind a property

of our component to the UI using a new type of binding we have not met before. So far we

have only looked at interpolation and output binding, which we have used to display the

properties of our component and to hook up events respectively.

Model binding uses a special syntax to bind a UI element to the backing component in a two-

way fashion:

[(ngModel)]= 'propertyName'

ngModel is a reserved identifier that Angular uses to reference the current model: in this case,

it is just the content of the backing component. If you have used the previous AngularJS, you

will be familiar with ngModel: all its features have been added to Angular 2+.

After all the hassle you went through in building these components, you may be relieved to

learn that to add our search feature, you just need a simple two-step operation. First, you

need to add a public searchText property to your BookListComponent class in

bookList.component.ts. You can also add an onSearch() method that will call the

getBooksFromREST() method on your booklist service passing the search text:

export class BookListComponent { public searchText: string; constructor(public bookListService: BookListService) { bookListService.getBooksFromREST(''); } onSearch() { this.bookListService.getBooksFromREST(this.searchText); } }

That is all the coding requirements fulfilled.

The second step, is to add the search text box to the UI, bind it to the searchText property of

your BookListComponent class, and add a blur event to the box that uses output binding to

fire the onSearch() method you just added.

Page 18: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 18 Blog Post 2

Brian Leach Consulting Limited Version 1.0

In the booklist.component.html file, add an input control into to the panel-heading row next

to the Book Listing title as below:

<div class="col col-xs-6"> <h3 class="panel-title">Book Listing</h3> </div> <div class="col col-xs-4"> <input (blur)="onSearch()" placeholder="Search Text" name="searchBox" [(ngModel)]="searchText"> </div>

Now you are good to go. Type a value into your new search box and see it take effect when

you tab or click away:

Now you have a searchable list that queries the server for matching titles and authors.

Adding Pagination

Using a search term to narrow down our listing has reduced the size of the data returned, but

it would still be useful to add some pagination to our table. We can do this in two ways:

Fetch all the data and then add pagination at the client.

Tell the service which page of data we need.

In most cases, the latter is probably more efficient. We can add pagination to our queries by

adding two more parameters to the QueryString: pageno and pagesize.

pageno=3&pagesize=20

Page 19: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 19 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Unfortunately, whilst this seems a good idea, the server does not tell us how many pages there

would be in total, so from a user feedback perspective it is not the most helpful. People expect

to be told how many pages of results to step through: so we will use local pagination for this

example. You can adapt the methods for using the pageno option at your leisure, including

lazy and background loading.

We can add local pagination to our class by fetching capturing the entire set of results, and

then binding the UI to just a subset of the data. Let’s add some simple logic to our BookList

service:

export class BookListService { books: BookSummary[]; pageBooks: BookSummary[]; currentPage: number; allPages: number; constructor(private _http: Http, @Inject('REST_URL') private restUrl:string) { } getBooksFromREST(searchTerm: string) { var uri = this.restUrl + "/U2_book_summary?sort=BY ID"; if (searchTerm) { uri = uri + '&select=TITLE LIKE "...' + searchTerm + '..." OR AUTHOR_NAME LIKE "...' + searchTerm + '..."'; } this._http.get(uri).subscribe( result => { this.books = result.json().U2_book_summary as BookSummary[]; this.getPage(1); }); } backPage() { if (this.currentPage > 1) { this.getPage(this.currentPage - 1); } } nextPage() { if (this.currentPage < this.allPages) { this.getPage(this.currentPage + 1); } } getPage(apage: number) { const pageSize = 10; this.pageBooks = []; var row = (apage - 1) * pageSize; for (var i = 0; (i < pageSize) && (row < this.books.length); i++) { this.pageBooks.push(this.books[row++]); } this.currentPage = apage; this.allPages = Math.floor(this.books.length / pageSize); }

Page 20: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 20 Blog Post 2

Brian Leach Consulting Limited Version 1.0

This now fetches the set, but places only the first 10 BookSummaries into a shortlist called

pageBooks. The nextPage() and backPage() methods will navigate and refresh that list.

Now we can hook all this up to the UI. Change the *ngFor directive used for creating the

rows so that it now looks at the pageBooks short-list instead of the full list of books:

*ngFor="let book of bookListService.pageBooks"

We can provide pagination control by adding the following to the table footer:

<div class="panel-footer"> <div class="row"> <div class="col col-xs-4"> Page {{bookListService.currentPage}} of {{bookListService.allPages}} </div> <div class="col col-xs-8"> <ul class="pagination pull-right"> <li><a (click)="onBack()">«</a></li> <li><a (click)="onNext()">»</a></li> </ul> </div> </div> </div>

Now our initial view is more manageable:

Page 21: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 21 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Connecting Components

You now have a searchable listing onto the books available in the U2 Incubator Bookstore.

This can be adapted into many kinds of display content: cards, sequences, details, these are

design decisions and outside the scope of this series.

Where you have componentization, there is also a need to route information between

components. Also, none of the components you have met so far perform any editing of their

content. We will see both in action as we create a maintenance component.

Creating the Data Resource

You created a summary view of the books for the listing. We now need a more detailed view

for the maintenance aspect.

Go into the U2 Restful Web Services Designer and by following the steps you completed

earlier, add a second Data Resource, again on the U2_BOOKS file. If the service is running, you

will need to stop it before you can amend the details or add a new resource.

This time select the following fields and name the resource U2_book_detail:

ID

TITLE

AUTHOR_ID

AUTHOR_NAME

ISBN

DEPT

GENRE

MEDIA

PUBLISHER_ID

PUBLISHER_NAME

SALE_PRICE

STOCK_LEVEL

ON_ORDER

TAX_CODE

TAX_RATE

SUPPLIER_ID

SUPPLIER_NAME

PURCH_PRICE

Accept the default naming for each of the fields. Remember to start the u2_book_server again

once you have added the new resource.

Creating the TypeScript Model

You will then need to add the TypeScript model to reflect this and to parse the JSON returned

from the RESTful service. We will be adding functionality to this one in the next post, so we

will make this a class rather than an interface.

Add a new TypeScript file named bookDetail.model.ts under your models folder, and fill in the

details to match the names of the fields selected above:

Page 22: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 22 Blog Post 2

Brian Leach Consulting Limited Version 1.0

export class BookDetail { public id: number; public title: string; public author_id: string; public author_name: string; public isbn: string; public dept: string; public genre: string; public media: string; public publisher_id: string; public publisher_name: string; public sale_price: number; public stock_level: number; public on_order: number; public tax_code: string; public tax_rate: number; public supplier_id: string; public supplier_name: string; public purch_price: number; }

Updating the Service

The book detail, just like the book listing, will be retrieved using the booklist service. This gives

us a single point for handling the books, that will be shared between these components. First

you will need to import your BookDetail model:

import { BookDetail } from '../models/bookDetail.model';

and add a selectedBook property to the class along with an editing property:

selectedBook: BookDetail = new BookDetail(); editing: boolean;

We are going to explicitly use a Promise when handling the response. For more details on this

see the previous article. This means you need to add three things to the imports: import { HttpModule, Http, Response } from '@angular/http'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise';

You can now add the method to retrieve a single book detail by record id to your class. This

will call the new service, but with a slightly more complex syntax than before: getBookFromREST(id: any) { var book: BookDetail = null; this.selectedBook = new BookDetail(); // ensure no nulls for template var p = this._http.get(this.restUrl + "/U2_book_detail/" + id) .map((response: Response) => response.json()) .toPromise() .catch(this.handleError) p.then(result => { this.selectedBook = result }); }

Page 23: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 23 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Why the additional step of mapping this into a Promise? First, it illustrates the Promise

architecture: instead of subscribing to the events, we map the result and tell it what to do

once it completes using the then() method. It also allows us to add some simple error handling: private handleError(error: any): Promise<any> { console.error('An error occurred', error); // for demo purposes only return Promise.reject(error.message || error); }

Notice that this returns a single item, not a collection. To retrieve the set of books we needed

to parse response.json().u2_book_summary, which is the name of the container. Here we only

need response.json().

Making the Connection

In the previous example, you used the ngModel to capture the search text entered in the

display list header. We will be using the same technique for the maintenance form, and

extending this to add some simple validation.

Before we do any of this, however, we want to make sure the call to the service is running and

that we can make this from our book listing.

Create a new folder under components and name it bookEditor.

Start by creating a minimal component with the following bookeditor.component.html:

<div class="container"> <h1>Book Title</h1> <div> Book Id : {{book.id}} <br /> Book Title : {{book.title}} <br /> Book Author : {{book.author_name}} </div> </div>

Add the following component definition into a new bookeditor.component.ts. There should

be no real surprises here.

import { BookDetail } from '../../models/bookDetail.model'; import { BookListService } from '../../services/booklist.service'; @Component({ providers: [BookListService], selector: 'book-editor', templateUrl: './bookeditor.component.html' }) export class BookEditorComponent { @Input() book: BookDetail; constructor(public bookListService: BookListService) { } }

Page 24: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 24 Blog Post 2

Brian Leach Consulting Limited Version 1.0

This should be sufficient to illustrate the routing between our book listing and the new

component. We need to pass a book id in response to clicking the Edit button on the listing.

This will cause the book service to fetch the book detail. We need to then expose this to the

book editor component, but the book listing and the book editor know nothing about one

another. We need to tell Angular to join the two.

Add the following line to the bottom of the booklist.component.html:

<book-editor [book]="bookListService.selectedBook"></book-editor>

This will display the book editor underneath the listing (you can deal with the design issues

later). As it does so, Angular maps the book property of the editor component to the

selectedBook property of the service.

Now, finally you can code up the edit button event on the BookListComponent:

onEdit(abook: BookSummary) { this.bookListService.editing = true; this.bookListService.getBookFromREST(abook.id); }

Time to run your project and make sure that the Edit button now fills out the details of the

title below. If you hit any errors, go back carefully over the steps and make sure you have not

forgotten anything.

Page 25: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 25 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Creating a Maintenance Form

Now you have two components on your page: a listing to select a title and a display of the title

details. We will turn that display into a maintenance form. As a prerequisite we need to import

a new reference to our project: the Angular Forms package. This adds validation, model

binding, submission control and other features.

Import the modules into the app.module.shared.ts:

import { FormsModule } from '@angular/forms';

Add this to the imports section, before the RouterModule:

imports: [ FormsModule, RouterModule.forRoot([

Creating the HTML Form

The look and feel of the form will come from the Bootstrap theming, so we can be pretty lean

about how we want to render this. We need a form containing form-groups of controls.

Angular uses this group to append a number of implicit directives about how the form will

operate. Each control is placed in a form-group div.

Start by creating a simple form. Change the bookeditor.component.html to hold a set of fields

as below:

<div class="container"> <h1>Book Title</h1> <form (ngSubmit)="onSubmit()" #bookForm="ngForm"> <div class="form-group"><label>id:</label>{{book.id}}</div> <div class="form-group"> <label>title:</label> <input class="form-control" [(ngModel)]="book.title" name="title" placeholder="title" required #title="ngModel"> </div> <div class="form-group"> <label>author:</label> <span>{{book.author_name}}</span> </div> <div class="form-group"> <label>dept:</label> <select class="form-control" [(ngModel)]="book.dept" name="dept" placeholder="dept" required> <option value="ADULT">ADULT</option> <option value="JUNIOR">JUNIOR</option> </select> </div> <div class="form-group">

Page 26: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 26 Blog Post 2

Brian Leach Consulting Limited Version 1.0

<label>ISBN:</label> <input class="form-control" [(ngModel)]="book.isbn" name="isbn" placeholder="ISBN"> </div> <div class="form-group"> <label>price:</label> <input class="form-control" [(ngModel)]="book.sale_price" name="salePrice" placeholder="sale price"> </div> <div class="form-group"> <label>stock:</label> <input class="form-control" [(ngModel)]="book.stock_level" name="stockLevel" placeholder="stock"> </div> </form> </div>

You should now have a form that looks similar to the one below. I agree, it’s not the most

exciting but that is beside the point.

Notice that we hard coded the list of departments into the HTML template. That may be well

and good for a binary choice, but we should extract this from the UI for something more

flexible, such as the list of genres. We will add that to the BookListService class as a property:

genres: string[] = ['BIOGRAPHY', 'BUSINESS', 'CLASSIC', 'CRIME', 'DARK_ROMANCE', 'DRAMA', 'FANTASY', 'FICTION', 'HISTORY', 'HUMOUR', 'LANGUAGE'];

Now we can consume this in our template:

<div class="form-group"> <label>genre:</label> <select class="form-control" [(ngModel)]="book.genre" name="genre" placeholder="genre" required> <option *ngFor="let genre of bookListService.genres" value={{genre}}>{{genre}}</option> </select> </div>

Page 27: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 27 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Adding Validation

As with any form, validation is important and should be carried out both on the client and the

server (you are receiving data from outside, and that could come from anywhere).

First, let us start with the title. We cannot save a book without a title. We signal this by adding

the required keyword, and binding this to the model: note that this is a new property called

title and not book.title:

required #title="ngModel"

We can now provide some user feedback. If no title is provided, we will display a message.

This can be placed in a hidden div as follows:

<div [hidden]="title.valid || title.pristine" class="alert alert-danger"> Title is required. </div>

This binds the hidden property of the div to two aspects of that title: valid and pristine. Angular

tracks the field and applies three CSS classes, which we can use to identify the state as well as

providing visual feedback:

touched or untouched

valid or invalid

pristine or dirty

Now we can present this simple validation if you clear the title field:

Let’s see what also happens when we add Submit and Reset buttons to the base of the form.

<button type="submit" class="btn btn-default" [disabled]="!bookForm.form.valid">Submit</button> <button class="btn btn-default" (click)="onClose($event); bookForm.reset()">Close</button>

Angular tracks the validation state of the form as a whole through formName.form.valid,

allowing us to enable and disable the Submit button. Notice that the button is also disabled

when no data is present.

Page 28: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 28 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Types of Validation

So what can we add as validations? First, we can add HTML validations to the fields: these will

be parsed by Angular and validations applied.

Let us tell Angular that the ISBN must be 10 characters long:

<input class="form-control" [(ngModel)]="book.isbn" name="isbn" placeholder="ISBN" minlength="10" maxlength="10" #isbn="ngModel">

We can differentiate the validation messages based on the errors property of the field. Note

that the whole section is controlled by an *ngIf:

<div *ngIf="isbn.errors && (isbn.dirty || isbn.touched)" class="alert alert-danger"> <div [hidden]="!isbn.errors.minlength">Must be at least 10 characters </div> <div [hidden]="!isbn.errors.maxlength">Cannot be over 10 characters long</div> </div>

HTML validation is sparse, so what about those little things like ensuring the price is numeric

and the stock is integral? For this we can use the HTML 5 pattern validation. This accepts a

regular expression.

You can read all about regular expressions in your own time, for now we can add these to the

price and stock level fields respectively:

<input class="form-control" [(ngModel)]="book.sale_price" name="salePrice"

placeholder="sale price" pattern="^\d+\.\d{2}$" #salePrice="ngModel">

<input class="form-control" [(ngModel)]="book.stock_level" name="stockLevel" placeholder="stock" pattern="^\d+$" #stockLevel="ngModel">

What about other validations. Angular must make that easy, right?

Erm, no. Not really. I said Angular is cool, I didn’t say it is complete. For that we must enter

the hairy world of custom validators and there simply isn’t time in these posts.

Page 29: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 29 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Putting Updates

You now have a form that can edit the book details and provide some simple validation. The

only problem is that it doesn’t save the details back.

We have two approaches we can take.

The simpler approach is to just use the u2_book_details Data Resource you have already

defined. Any data resource is two-way: by specifying the http verb we can GET a single

resource or collection, or we can PUT our changes back. This is probably a bad idea but we

start with this anyway.

The PUT request, like the GET requests, will run from the booklist service. We need to add a

couple of things to our imports before we can make full use of this:

import { HttpModule, Http, Response,Headers,RequestOptions } from

'@angular/http';

The U2 RESTful Web Services use a simple form of optimistic control to ensure that updates

are captured. When you request a Data Resource, in addition to the fields mapped from the

file there is a u2version field appended. This holds a kind of timestamp to identify this instance

of the record in the collection:

The service will only update the book if the same version number is sent back, to make sure

that no intervening changes have been made. Unfortunately, for reasons best known to the

engineers, this is not provided as part of the return data but using a Match-If HTTP header.

Page 30: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 30 Blog Post 2

Brian Leach Consulting Limited Version 1.0

In any case, you first need to capture this version, so add this to the bottom of the

bookDetail.model.ts model:

public purch_price: number; public u2version: string; }

Next add a new method to the BookListService class. This will call the http.put() method

passing the book as a JSON string and adding in the new headers. The syntax is a little tortuous

but necessary.

writeBookToREST (book: BookDetail): Promise<BookDetail> { let headers = new Headers(); headers.append('Content-Type', 'application/json'); headers.append('If-Match', book.u2version); let options = new RequestOptions({ headers: headers }); var body = JSON.stringify(book); return this._http.put(this.restUrl + "/U2_book_detail/" + book.id, body, options) .toPromise() .then(() => book) .catch(this.handleError); }

Now this can be called from the submit button by wiring up the OnSubmit() method on the

BookEditorComponent. You can also handle the onClose event from the close button whilst

you are at it:

onSubmit() { this.bookListService.writeBookToREST(this.book); this.bookListService.editing = false; } onClose(event: any) { this.bookListService.editing = false; event.stopPropagation(); }

Finally, you should be able to run the editor and update the U2_BOOKS record on the server.

If not, see below for one possible reason.

Note that only the fields that make up the BookDetails are updated: this is unlike the regular

MultiValue model where the whole record is read, updated and then written back. Any fields

not part of the BookDetails are undisturbed.

Page 31: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 31 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Notice

If you are using Chrome, you may get an error regarding Cross Origin Resource Sharing (CORS).

Chrome sends an OPTIONS request before the real call to check whether the server allows

cross origin requests, signalled by a server response including an Access-Control-Allow-Origin

header. If this is not returned the browser will not perform the subsequent PUT or POST call.

The RESTful services does not respond to this request before version 4.2.0 and so Chrome

denies access. You may see this if you open the Developer Tools from the Settings menu and

go to the Console View.

If you hit this, the simplest option for now is to update your copy of the U2 Restful Web

Services or to disable CORS when starting Chrome from Visual Studio.

Add a new Browse With … entry to start Chrome with the options:

--disable-web-security --user-data-dir

Page 32: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 32 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Calling a Subroutine

As always, it should go without saying that directly updating a file from an external resource

is a really bad idea.

Instead, we will replace this with a call to a subroutine to perform the update. This allows us

to validate correctly and to add any further processing. Let’s start simple by just capturing

what we are sending back.

To illustrate the process of calling a subroutine, create the following subroutine in the

books.bp file in the u2_books account and make sure you compile and catalog it.

As you can see, this will only capture and log the incoming book details.

In the U2 Restful Web Services Developer, stop the u2_book_server and expand the list of

catalogued programs in the u2_books account in the U2 Resources panel above. You should

find your UpdateBookFromREST subroutine.

Drag and drop this onto the Subroutine Resources under the u2_book_server. This prompts

you to define the subroutine parameters as below:

Page 33: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 33 Blog Post 2

Brian Leach Consulting Limited Version 1.0

To call a subroutine we need to make a POST call to the URI:

{your_server}/u2_books/subroutine/{subroutine_name}

The post request body must include a JSON object that contains each of the input parameters

identified using the name in the definition.

To see this in practice, change the writeBookToREST on the BookListService to make this call.

Note that we no longer need to send down the If-Match header as we are not asking the

RESTful service to resolve any lock conflicts on our behalf:

writeBookToREST(book: BookDetail): Promise<BookDetail> { var headers = new Headers(); headers.append('Content-Type', 'application/json'); let options = new RequestOptions({ headers: headers }); var body = JSON.stringify({ 'BookDetails': book }); return this._http.post( this.restUrl + "/subroutine/UpdateBookFromREST", body, options) .toPromise() .then(() => book) .catch(this.handleError); }

Page 34: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 34 Blog Post 2

Brian Leach Consulting Limited Version 1.0

This time, when you hit the submit button it will call the subroutine to write the input data to

the REST_DEBUG entry in your VOC file:

>ED VOC REST_DEBUG

1 lines long.

----: p

0001: {"publisher_id":"018","author_name":"Alexander McCall

Smith","publisher_name":"Bolinda Audio","isbn":"1405500530","stock_level":"6",

"media":"TAPE","dept":"ADULT","title":"Friends, Lovers, Chocolate Bunnies of the

Apocalypse","purch_price":"4.99","u2version":"7929494882365574422",

"sale_price":"14.99","@uri":"http://workvm:9193/u2_books/U2_book_detail/3",

"on_order":"","genre":"FICTION","id":"3","author_id":"2","supplier_name":"NISBETT

AND NIFFLIN","supplier_id":"NN"}

Bottom at line 1.

----: EX

Mapping the Subroutine Parameters

This provides access to the data sent as part of the request - but as a string, which is not hugely

useful unless you already have your own JSON parsing routines (many sites do). However, the

U2 RESTful Services has two other ways to represent data passed to and from subroutines.

The default parameter type is simply string, which passes the content through with minimal

intervention. You can also specify a type of json, which will pass the data as a UDO (Universal

Data Object). This is most useful for complex, nested or otherwise unstructured entities. You

can read about UDOs in the UniVerse Basic Extensions guide.

As a more developer-friendly option, the U2 RESTful service can also parse the content of a

JSON-formatted parameter on your behalf into or out of a regular dynamic array using a

mapping definition similar to the TypeScript model you created on the client. The array

definitions are created as separate resources so that they can be shared between multiple

subroutines.

Under the Subroutine Resources section of your u2_book_server service you will find the

Dynamic Array Definitions.

Page 35: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 35 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Right click this folder and select New Dynamic Array. Here you can map JSON keys to locations

in the array. For each field, you define the location and MultiValue handling. You do not need

to map every field in the incoming JSON message, so complete this for only the local fields in

the BookDetail model that relate directly to the U2_BOOKS file.

Now you can change the subroutine definition to expect a dynamic array in this format.

Remember that you need to stop the service before you can amend any of the details.

Right click the UpdateBookFromREST subroutine and select Properties. Edit the BookDetails

input parameter and set the Type to dynamic array and the array name to BookDetailsArray:

Page 36: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 36 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Now, without changing the subroutine, this will store the details as a regular array.

>CT VOC REST_DEBUG

REST_DEBUG

0001 4

0002 The Legend of Spud Murphy

0003 3

0004 0141805293

0005 JUNIOR

0006 FANTASY

0007 CD

0008 003

0009 5.99

0010 4

0011

0012

0013 1.99

I will leave it to you to write the production logic to allow your UpdateBookFromREST

subroutine to update the U2_BOOKS file with these details: that is just bread-and-butter

Business Language coding.

Do be aware, of course, you would need to come up with a scheme for concurrency handling

were you to apply this to real world situations, whether merging or including a checksum in

your data or having some other means of handling and resolving conflicts. RESTful services,

like all web technologies, are stateless, and so you cannot rely on the safer but less scalable

pessimistic locking model that underpins traditional MultiValue applications.

Page 37: Angular, REST and U2 - The Rocket Software Blog · PDF fileAngular, REST and U2 Blog Post 2 . Angular, ... fields, that you want to make available. This is contextual - you can create

Angular, REST and U2 Page 37 Blog Post 2

Brian Leach Consulting Limited Version 1.0

Next Steps

In this post, we have introduced the Rocket U2 RESTful Web Services and used these to fetch

data from regular files using dictionary items. We have also discovered how to write back data

using PUT requests, and how to call subroutines using POST.

On the browser side, we have discovered how to write new Angular components and to link

these together to form a workflow. Now that you have seen the progression, you can add

some sophistication to the UI by toggling between the list and editor views.

In the next and final post in this series, we will add some more features to the Angular UI, and

look at another model for creating RESTful services to surface your U2 data and subroutines.

Here we will look at how to leverage the Microsoft WebAPI to call into your server using the

UniObjects protocol.