brandonroberts / vladivostok-sample

1 stars 0 forks source link

CrisisCenter: DialogService.confirm should return a promise (and observable?) #7

Closed wardbell closed 8 years ago

wardbell commented 8 years ago

Current implementation blocks and returns a boolean. That's not realistic.

Re-implement confirm to return a promise.

import { Injectable } from '@angular/core';
/**
 * Async modal dialog service
 * DialogService makes this app easier to test by faking this service.
 * TODO: better modal implemenation that doesn't use window.confirm
 */
@Injectable()
export class DialogService {
  /**
   * Ask user to confirm an action. `message` explains the action and choices.
   * Returns promise resolving to `true`=confirm or `false`=cancel
   */
  confirm(message?: string): Promise<boolean> {
    return new Promise<boolean>(resolve => {
      setTimeout(() => {
        let ok = window.confirm(message || 'Is it OK?') ;
        return resolve(ok);
        },  0);
    })
    // Todo: good during development; delete
    .then(ok => {
      console.log('confirm said: ' + ok);
      return ok;
    });
}

This still won't work because router doesn't understand promises, only observables (see Issue #8).

Therefore, would have to EITHER have to implement as Observable here or consume as Observable in the guard:

import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { DialogService } from '../dialog.service';
import { CrisisDetailComponent } from './crisis-detail.component';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromPromise';

@Injectable()
export class CanDeactivateCrisisDetail implements CanDeactivate<CrisisDetailComponent> {
  constructor(private dialog: DialogService) {}

  canDeactivate(component: CrisisDetailComponent): Observable<boolean> | boolean {
    // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
    if (!component.crisis || component.crisis.name === component.editName) {
      return true;
    }
    // Otherwise ask the user with the dialog service and return its promise
    // which resolves to true or false when the user decides
    // as an observable
    let p = this.dialog.confirm('Discard changes?');
    let o = Observable.fromPromise(p);
    return o;
  }
}

But this isn't working either. Async deactivate not working; see issue #9

brandonroberts commented 8 years ago

Fixed via https://github.com/angular/vladivostok/commit/0b991e3a67eda542206ae927cbe9ffc3a6336df1