Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit b97bef8

Browse files
author
Sam Graber
authored
Merge pull request #364 from SamGraber/multiple_requests
Managing the subscriber
2 parents 7eb0f9f + b72a98a commit b97bef8

File tree

24 files changed

+131
-103
lines changed

24 files changed

+131
-103
lines changed

bootstrapper/app.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ angular.module(moduleName, [
7171
miscModuleName,
7272
textModuleName,
7373
])
74-
.directive('tsApp', <any>upgradeAdapter.downgradeNg2Component(App));
74+
.directive('tsApp', <any>upgradeAdapter.downgradeNg2Component(App))
75+
.directive('tsMiscNgContext', <any>upgradeAdapter.downgradeNg2Component(MiscNgContextBootstrapper));
7576

7677
@NgModule({
7778
imports: [

bootstrapper/forms/formsNg2.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ <h5>Form with names</h5>
2727
<rlButtonSubmit rightAligned="true">Submit right</rlButtonSubmit>
2828
</rlForm>
2929
<h5>Autosave form</h5>
30+
<rlBusy #testBusy></rlBusy>
3031
<rlBusy [loading]="(autosaveAction.saving$ | async) || (autosaveAction.complete$ | async)"></rlBusy>
31-
<rlForm #autosaveForm [save]="waitCallback" rlAutosave [saveWhenInvalid]="true">
32+
<rlForm #autosaveForm [save]="saveRequest" rlAutosave [saveWhenInvalid]="true">
3233
<rlTextbox name="textbox1" label="Autosave textbox" rlRequired="Required textbox"></rlTextbox>
3334
</rlForm>
3435
{{autosaveForm.form.pristine ? 'Pristine' : 'Dirty'}}

bootstrapper/forms/formsNg2Bootstrapper.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Component, ViewChild } from '@angular/core';
22
import { Observable, BehaviorSubject } from 'rxjs';
3+
import { HttpUtility } from 'rl-http';
34

5+
import { BusyComponent } from '../../source/components/busy/busy';
46
import { FormComponent } from '../../source/components/form/form';
57
import { AutosaveActionService } from '../../source/services/autosaveAction/autosaveAction.service';
68

@@ -16,11 +18,15 @@ export class FormsBootstrapper {
1618
rating$: BehaviorSubject<any>;
1719

1820
@ViewChild('testForm') testForm: FormComponent;
21+
@ViewChild('testBusy') testBusy: BusyComponent;
1922

2023
autosaveAction: AutosaveActionService;
24+
http: HttpUtility;
2125

22-
constructor(autosaveAction: AutosaveActionService) {
26+
constructor(autosaveAction: AutosaveActionService
27+
, http: HttpUtility) {
2328
this.autosaveAction = autosaveAction;
29+
this.http = http;
2430

2531
this.rating$ = new BehaviorSubject(null);
2632

@@ -46,6 +52,11 @@ export class FormsBootstrapper {
4652
});
4753
}
4854

55+
saveRequest = data => {
56+
const request = this.http.post('http://localhost:8000/test', data).delay(1000);
57+
this.testBusy.waitOn(request).subscribe(response => console.log(response));
58+
};
59+
4960
saveTestForm = (data): any => {
5061
if (this.testForm.form.dirty) {
5162
return this.waitCallback(data);

bootstrapper/misc/miscNg2Context.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ export class MiscNgContextBootstrapper {
1717
}
1818

1919
toggle(): void {
20-
this.busy2.trigger(!this.busy2.loading);
20+
this.busy2.waitOn(!this.busy2.loading);
2121
}
22-
}
22+
}

source/behaviors/autosave/autosave.tests.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Subject } from 'rxjs';
1+
import { Observable, Subject } from 'rxjs';
22
import { rlFakeAsync, mock, rlTick, flushMicrotasks } from 'rl-async-testing';
33

44
import { AutosaveDirective, DEFAULT_AUTOSAVE_DEBOUNCE } from './autosave';
@@ -12,7 +12,7 @@ interface IFormMock {
1212
}
1313

1414
interface IAutosaveActionMock {
15-
trigger: Sinon.SinonSpy;
15+
waitOn: Sinon.SinonSpy;
1616
}
1717

1818
describe('AutosaveDirective', () => {
@@ -31,7 +31,7 @@ describe('AutosaveDirective', () => {
3131
saveForm: sinon.spy(),
3232
};
3333

34-
autosaveAction = { trigger: sinon.spy() };
34+
autosaveAction = { waitOn: sinon.spy(() => Observable.empty()) };
3535

3636
autosave = new AutosaveDirective(<any>form, <any>autosaveAction);
3737
});
@@ -177,8 +177,8 @@ describe('AutosaveDirective', () => {
177177

178178
autosave.autosave();
179179

180-
sinon.assert.calledOnce(autosaveAction.trigger);
181-
sinon.assert.calledWith(autosaveAction.trigger, waitValue);
180+
sinon.assert.calledOnce(autosaveAction.waitOn);
181+
sinon.assert.calledWith(autosaveAction.waitOn, waitValue);
182182
});
183183

184184
it('should save the form directly if saveWhenInvalid is true', () => {
@@ -188,8 +188,8 @@ describe('AutosaveDirective', () => {
188188

189189
autosave.autosave();
190190

191-
sinon.assert.calledOnce(autosaveAction.trigger);
192-
sinon.assert.calledWith(autosaveAction.trigger, waitValue);
191+
sinon.assert.calledOnce(autosaveAction.waitOn);
192+
sinon.assert.calledWith(autosaveAction.waitOn, waitValue);
193193
});
194194

195195
it('should not save if the form becomes pristine immediately before saving', () => {

source/behaviors/autosave/autosave.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ export class AutosaveDirective implements AfterViewInit {
5757

5858
const waitOn = this.submitAndWait();
5959
if (waitOn) {
60-
this.autosaveAction.trigger(waitOn);
60+
// subscribes to kick off the stream
61+
this.autosaveAction.waitOn(waitOn).subscribe();
6162
}
6263
}
6364

source/components/busy/busy.tests.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@ describe('busy', () => {
1111
});
1212

1313
it('should not show the spinner after triggering if null', (): void => {
14-
busy.trigger(null);
14+
busy.waitOn(null);
1515
expect(busy.loading).to.not.exist;
1616
});
1717

1818
it('should show the spinner after triggering if true', (): void => {
19-
busy.trigger(true);
19+
busy.waitOn(true);
2020
expect(busy.loading).to.be.true;
2121
});
2222

2323
it('should hide the spinner after triggering if false', (): void => {
2424
busy.loading = true;
25-
busy.trigger(false);
25+
busy.waitOn(false);
2626
expect(busy.loading).to.be.false;
2727
});
2828

@@ -32,7 +32,7 @@ describe('busy', () => {
3232
beforeEach((): void => {
3333
stream = new Subject<void>();
3434

35-
busy.trigger(stream);
35+
busy.waitOn(stream).subscribe({ error: () => null });
3636

3737
expect(busy.loading).to.be.true;
3838
});

source/components/busy/busy.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Component, Input } from '@angular/core';
22
import { isBoolean } from 'lodash';
3+
import { Observable } from 'rxjs';
34

45
import { DefaultTheme } from '../componentsDefaultTheme';
56
import { AsyncHelper, IWaitValue } from '../../services/async/async.service';
@@ -26,18 +27,18 @@ export class BusyComponent {
2627
/*
2728
* Public API for triggering the rlBusy to wait on a promise
2829
*/
29-
trigger(waitOn: IWaitValue<any>): void {
30+
waitOn(waitOn: IWaitValue<any>): Observable<any> {
3031
if (waitOn == null) {
31-
return;
32+
return Observable.empty();
3233
}
3334

3435
if (isBoolean(waitOn)) {
3536
this.loading = waitOn;
36-
return;
37+
return Observable.of(waitOn);
3738
}
3839

3940
this.loading = true;
40-
this.asyncHelper.waitAsObservable(waitOn)
41-
.subscribe(null, () => this.loading = false, () => this.loading = false);
41+
return this.asyncHelper.waitAsObservable(waitOn)
42+
.do(null, () => this.loading = false, () => this.loading = false);
4243
}
43-
}
44+
}

source/components/buttons/buttonAsync/buttonAsync.tests.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { ButtonAsyncComponent } from './buttonAsync';
1+
import { Observable } from 'rxjs';
2+
3+
import { ButtonAsyncComponent } from './buttonAsync';
24

35
interface IMockBusy {
4-
trigger: Sinon.SinonSpy;
6+
waitOn: Sinon.SinonSpy;
57
}
68

79
describe('ButtonAsyncComponent', () => {
@@ -13,7 +15,7 @@ describe('ButtonAsyncComponent', () => {
1315
button = new ButtonAsyncComponent();
1416

1517
busy = {
16-
trigger: sinon.spy(),
18+
waitOn: sinon.spy(() => Observable.empty()),
1719
};
1820
button.busySpinner = <any>busy;
1921
});
@@ -27,7 +29,7 @@ describe('ButtonAsyncComponent', () => {
2729

2830
sinon.assert.calledOnce(action);
2931
sinon.assert.calledWith(action, event);
30-
sinon.assert.calledOnce(busy.trigger);
31-
sinon.assert.calledWith(busy.trigger, 5);
32+
sinon.assert.calledOnce(busy.waitOn);
33+
sinon.assert.calledWith(busy.waitOn, 5);
3234
});
3335
});

source/components/buttons/buttonAsync/buttonAsync.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ export class ButtonAsyncComponent extends BaseButtonComponent {
2323
constructor() {
2424
super();
2525
if (!this.action) {
26-
this.action = <IAsyncAction>() => Promise.resolve();
26+
this.action = () => Observable.empty();
2727
}
2828
}
2929

3030
triggerAction($event: any): void {
31+
// subscribes to kick off the action
3132
const waitValue: IWaitValue<any> = this.action($event);
32-
this.busySpinner.trigger(waitValue);
33+
this.busySpinner.waitOn(waitValue).subscribe();
3334
}
3435
}

source/components/buttons/buttonLongClick/buttonLongClick.tests.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Observable } from 'rxjs';
12
import { rlFakeAsync, rlTick, flushMicrotasks } from 'rl-async-testing';
23

34
import { services } from 'typescript-angular-utilities';
@@ -6,7 +7,7 @@ import __timeout = services.timeout;
67
import { ButtonLongClickComponent } from './buttonLongClick';
78

89
interface IMockBusy {
9-
trigger: Sinon.SinonSpy;
10+
waitOn: Sinon.SinonSpy;
1011
}
1112

1213
interface IMockNotification {
@@ -27,7 +28,7 @@ describe('ButtonLongClickComponent', () => {
2728
button = new ButtonLongClickComponent(<any>notification, new __timeout.TimeoutService());
2829

2930
busy = {
30-
trigger: sinon.spy(),
31+
waitOn: sinon.spy(() => Observable.empty()),
3132
};
3233
button.busySpinner = <any>busy;
3334
});
@@ -46,8 +47,8 @@ describe('ButtonLongClickComponent', () => {
4647

4748
sinon.assert.calledOnce(action);
4849
sinon.assert.calledWith(action, event);
49-
sinon.assert.calledOnce(busy.trigger);
50-
sinon.assert.calledWith(busy.trigger, 5);
50+
sinon.assert.calledOnce(busy.waitOn);
51+
sinon.assert.calledWith(busy.waitOn, 5);
5152
}));
5253

5354
it('should cancel and show a warning if the user stops the action before the time is up', rlFakeAsync((): void => {
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1+
import { Observable } from 'rxjs';
12
import { ButtonSubmitComponent } from './buttonSubmit';
23

34
interface IMockForm {
45
submitAndWait: Sinon.SinonSpy;
56
}
67

78
interface IMockBusy {
8-
trigger: Sinon.SinonSpy;
9+
waitOn: Sinon.SinonSpy;
910
}
1011

1112
interface IMockExceptionHandler {
1213
call: Sinon.SinonSpy;
1314
}
1415

15-
describe('button submit', (): void => {
16+
describe('ButtonSubmitComponent', (): void => {
1617
let buttonSubmit: ButtonSubmitComponent;
1718
let form: IMockForm;
1819
let busy: IMockBusy;
@@ -24,7 +25,7 @@ describe('button submit', (): void => {
2425
buttonSubmit = new ButtonSubmitComponent(<any>form);
2526

2627
busy = {
27-
trigger: sinon.spy(),
28+
waitOn: sinon.spy(() => Observable.empty()),
2829
};
2930
buttonSubmit.busySpinner = <any>busy;
3031
});
@@ -33,7 +34,7 @@ describe('button submit', (): void => {
3334
buttonSubmit.submit();
3435

3536
sinon.assert.calledOnce(form.submitAndWait);
36-
sinon.assert.calledOnce(busy.trigger);
37-
sinon.assert.calledWith(busy.trigger, 5);
37+
sinon.assert.calledOnce(busy.waitOn);
38+
sinon.assert.calledWith(busy.waitOn, 5);
3839
});
39-
});
40+
});

source/components/buttons/buttonSubmit/buttonSubmit.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ export class ButtonSubmitComponent extends BaseButtonComponent {
2121
}
2222

2323
submit(): void {
24-
const waitValue: IWaitValue<any> = this.form.submitAndWait();
25-
this.busySpinner.trigger(waitValue);
24+
// subscribes to kick off the action
25+
const request = this.form.submitAndWait();
26+
this.busySpinner.waitOn(request).subscribe();
2627
}
2728
}

source/components/cardContainer/card/card.tests.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Observable } from 'rxjs';
12
import { filter } from 'lodash';
23

34
import { services } from 'typescript-angular-utilities';
@@ -62,6 +63,7 @@ describe('CardComponent', () => {
6263

6364
describe('toggle', (): void => {
6465
it('should toggle the card content', (): void => {
66+
card.saveForm = sinon.spy(() => Observable.empty());
6567
expect(card.showContent$.getValue()).to.be.false;
6668

6769
card.toggleContent();

source/components/dialog/dialog.tests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ describe('DialogComponent', (): void => {
7272
});
7373

7474
it('should close the dialog when the submit completes', (): void => {
75-
dialog.submitAndClose();
75+
dialog.submitAndClose().subscribe();
7676

7777
sinon.assert.calledOnce(submitAndWaitSpy);
7878
sinon.assert.notCalled(closeSpy);
@@ -83,7 +83,7 @@ describe('DialogComponent', (): void => {
8383
});
8484

8585
it('should not close the dialog if the submit returns false', (): void => {
86-
dialog.submitAndClose();
86+
dialog.submitAndClose().subscribe();
8787

8888
sinon.assert.calledOnce(submitAndWaitSpy);
8989
sinon.assert.notCalled(closeSpy);

source/components/dialog/dialog.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Observable } from 'rxjs';
12
import { Component, Input, ContentChild, forwardRef } from '@angular/core';
23

34
import { services } from 'typescript-angular-utilities';
@@ -6,7 +7,7 @@ import __notification = services.notification;
67
import { DialogRootService, IDialogClosingHandler } from './dialogRoot.service';
78
import { DialogHeaderTemplate, DialogContentTemplate, DialogFooterTemplate } from './templates/index';
89
import { FormComponent, baseInputs } from '../form/form';
9-
import { AsyncHelper, IWaitValue } from '../../services/async/async.service';
10+
import { AsyncHelper } from '../../services/async/async.service';
1011
import { FormService } from '../../services/form/form.service';
1112

1213
@Component({
@@ -60,14 +61,13 @@ export class DialogComponent extends FormComponent {
6061
this.dialogRoot.closeDialog.next(null);
6162
}
6263

63-
submitAndClose(): IWaitValue<any> {
64+
submitAndClose(): Observable<any> {
6465
const waitOn = this.submitAndWait();
65-
this.asyncHelper.waitAsObservable(waitOn).subscribe((result) => {
66+
return this.asyncHelper.waitAsObservable(waitOn).do((result) => {
6667
if (result !== false) {
6768
this.close();
6869
}
6970
});
70-
return waitOn;
7171
}
7272

7373
wrapOnClosing: IDialogClosingHandler = () => {

0 commit comments

Comments
 (0)