Skip to content

Commit d2b3cb2

Browse files
committed
Binding and Store tutorials
1 parent fb0f584 commit d2b3cb2

File tree

13 files changed

+178
-11
lines changed

13 files changed

+178
-11
lines changed

cloudapp/src/app/app-routing.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { SettingsComponent } from './settings/settings.component';
77
import { ParallelComponent } from './parallel/parallel.component';
88
import { ExternalComponent } from './external/external.component';
99
import { XmlComponent } from './xml/xml.component';
10+
import { BindComponent } from './bind/bind.component';
11+
import { StoreComponent } from './store/store.component';
1012

1113
const routes: Routes = [
1214
{ path: '', component: MainComponent },
@@ -16,6 +18,8 @@ const routes: Routes = [
1618
{ path: 'parallel', component: ParallelComponent },
1719
{ path: 'external', component: ExternalComponent },
1820
{ path: 'xml', component: XmlComponent },
21+
{ path: 'bind', component: BindComponent },
22+
{ path: 'store', component: StoreComponent },
1923
];
2024

2125
@NgModule({

cloudapp/src/app/app.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { SettingsComponent } from './settings/settings.component';
1616
import { ParallelComponent } from './parallel/parallel.component';
1717
import { ExternalComponent } from './external/external.component';
1818
import { XmlComponent } from './xml/xml.component';
19+
import { BindComponent } from './bind/bind.component';
20+
import { StoreComponent } from './store/store.component';
1921

2022
export function getToastrModule() {
2123
return ToastrModule.forRoot({
@@ -34,7 +36,9 @@ export function getToastrModule() {
3436
SettingsComponent,
3537
ParallelComponent,
3638
ExternalComponent,
37-
XmlComponent
39+
XmlComponent,
40+
BindComponent,
41+
StoreComponent
3842
],
3943
imports: [
4044
MaterialModule,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<div *ngIf="form; else noitem">
2+
<p><strong>BIB Title:</strong> {{ form.get('bib_data.title').value }}</p>
3+
<form [formGroup]="form">
4+
<ng-container formGroupName="item_data">
5+
<mat-form-field>
6+
<mat-label>Barcode</mat-label>
7+
<input matInput formControlName="barcode">
8+
</mat-form-field>
9+
<mat-form-field>
10+
<mat-label>Enumeration A</mat-label>
11+
<input matInput formControlName="enumeration_a">
12+
</mat-form-field>
13+
<mat-form-field>
14+
<mat-label>Chronology I</mat-label>
15+
<input matInput formControlName="chronology_i">
16+
</mat-form-field>
17+
</ng-container>
18+
</form>
19+
<div class="commands-container">
20+
<button mat-stroked-button type="button" color="primary" (click)="save()" [disabled]="!form.dirty">Save</button>
21+
<mat-spinner diameter="30" class="spinner" *ngIf="saving"></mat-spinner>
22+
</div>
23+
</div>
24+
<ng-template #noitem>
25+
Please navigate to an item record.
26+
</ng-template>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mat-form-field {
2+
width: 100%
3+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Component, OnInit, OnDestroy } from '@angular/core';
2+
import { AppService } from '../app.service';
3+
import { FormGroup } from '@angular/forms';
4+
import { CloudAppRestService, CloudAppEventsService, PageInfo, HttpMethod } from '@exlibris/exl-cloudapp-angular-lib';
5+
import { Subscription } from 'rxjs';
6+
import { finalize, switchMap, tap } from 'rxjs/operators';
7+
import { ToastrService } from 'ngx-toastr';
8+
import { toFormGroup } from '../utils'
9+
10+
@Component({
11+
selector: 'app-bind',
12+
templateUrl: './bind.component.html',
13+
styleUrls: ['./bind.component.scss']
14+
})
15+
export class BindComponent implements OnInit, OnDestroy {
16+
private pageLoad$: Subscription;
17+
form: FormGroup;
18+
saving = false;
19+
20+
constructor(
21+
private appService: AppService,
22+
private restService: CloudAppRestService,
23+
private eventsService: CloudAppEventsService,
24+
private toastr: ToastrService
25+
) { }
26+
27+
ngOnInit() {
28+
this.appService.setTitle('Model Binding');
29+
this.pageLoad$ = this.eventsService.onPageLoad((pageInfo: PageInfo) => {
30+
const entities = (pageInfo.entities||[]).filter(e=>e.type=='ITEM');
31+
if (entities.length > 0) {
32+
this.restService.call(entities[0].link)
33+
.subscribe(res=>this.form = toFormGroup(res) as FormGroup);
34+
}
35+
});
36+
}
37+
38+
ngOnDestroy() {
39+
this.pageLoad$.unsubscribe();
40+
}
41+
42+
save() {
43+
this.saving = true;
44+
this.restService.call({
45+
url: this.form.get('link').value,
46+
requestBody: this.form.value,
47+
method: HttpMethod.PUT
48+
}).pipe(
49+
switchMap(res => this.eventsService.refreshPage()),
50+
tap(() => this.toastr.success('Item updated')),
51+
finalize(() => this.saving=false)
52+
)
53+
.subscribe({
54+
error: e => this.toastr.error(e.message)
55+
});
56+
}
57+
}

cloudapp/src/app/main/main.component.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ <h1>
1010
<li><a [routerLink]="['parallel']">Making parallel API requests</a></li>
1111
<li><a [routerLink]="['external']">Reaching outside your app</a></li>
1212
<li><a [routerLink]="['xml']">Working with bibliographic records in XML</a></li>
13+
<li><a [routerLink]="['bind']">Model binding with REST objects</a></li>
14+
<li><a [routerLink]="['store']">Using the Store Service</a></li>
1315
</ul>
1416
</section>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<form [formGroup]="form">
2+
<textarea matInput formControlName="content"></textarea>
3+
</form >
4+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
textarea {
2+
width: 90%;
3+
margin: 10px;
4+
height: 100px;
5+
padding: 10px;
6+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Component, OnInit } from '@angular/core';
2+
import { AppService } from '../app.service';
3+
import { FormGroup, FormControl } from '@angular/forms';
4+
import { debounceTime, switchMap } from 'rxjs/operators';
5+
import { CloudAppStoreService } from '@exlibris/exl-cloudapp-angular-lib';
6+
import { toFormGroup } from '../utils';
7+
8+
const FORM_NAME = 'StoreForm';
9+
10+
@Component({
11+
selector: 'app-store',
12+
templateUrl: './store.component.html',
13+
styleUrls: ['./store.component.scss']
14+
})
15+
export class StoreComponent implements OnInit {
16+
form: FormGroup;
17+
18+
constructor(
19+
private appService: AppService,
20+
private storeService: CloudAppStoreService
21+
) { }
22+
23+
ngOnInit() {
24+
this.appService.setTitle('Store Service');
25+
this.form = new FormGroup({
26+
content: new FormControl()
27+
});
28+
29+
this.storeService.get(FORM_NAME).subscribe( value => {
30+
if (value) {
31+
this.form = toFormGroup(value) as FormGroup;
32+
}
33+
34+
this.form.valueChanges.pipe(
35+
debounceTime(500),
36+
switchMap(val=>this.storeService.set(FORM_NAME, val))
37+
).subscribe()
38+
})
39+
}
40+
}

cloudapp/src/app/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { AbstractControl, FormArray, FormGroup, FormControl } from "@angular/forms";
2+
3+
export function toFormGroup (object: Object): AbstractControl {
4+
if (Array.isArray(object)) {
5+
return new FormArray(object.map(entry=>toFormGroup(entry)));
6+
} else if (typeof object === 'object' && object != null) {
7+
return new FormGroup(mapObject(object, obj => toFormGroup(obj)));
8+
} else {
9+
return new FormControl(object);
10+
}
11+
}
12+
13+
function mapObject (object: Object, mapFn: Function) {
14+
return Object.keys(object).reduce(function(result, key) {
15+
result[key] = mapFn(object[key])
16+
return result
17+
}, {})
18+
}
19+

0 commit comments

Comments
 (0)