ngrx: ожидание подтверждения или отмены в пользовательском диалоге - PullRequest
2 голосов
/ 04 июня 2019

нгркс, угловой 7

Мне нужно удалить элемент из списка, но перед тем, как отобразить диалоговое окно для подтверждения. Я думаю, что лучший подход для меня - показать диалог через побочный эффект . Мне нужно показать, когда было удалено действие удаления, поймать его в побочном эффекте, открыть компонент диалога и вернуть некое обещание (подтвердить или отменить). Я немного сбит с толку, поэтому мне нужна ваша помощь, дорогой Stackoverflow.

list.component.ts

export class ListComponent {

    list: List;

    constructor(store: Store<fromStore.State>) { }

    deleteItem(itemId: string) {
        this.store.dispatch(new fromStore.DeleteItem);
    }
}

Confirm-dialog.component.ts

export class ConfirmDialogComponent {

    constructor() { }

    confirm() {
        // return something to confirm deleting
    }

    cancel() {
        // return something to cancel deleting
    }
}

list.actions.ts

export enum ListActionTypes {
    DeleteItem = '[List] Delete Item',
    DeleteItemSuccess = '[List] Delete Item Success',
    DeleteItemFailure = '[List] Delete Item Failure',

    SetDialogVisibility = '[List] Set Dialog Visibility'
}

export class DeleteItem implements Action {
    readonly type = ListActionTypes.DeleteItem;

    constructor(public payload: string) { } // item id
}

export class DeleteItemSuccess implements Action {
    readonly type = ListActionTypes.DeleteItemSuccess;

    constructor(public payload: string) { }
}

export class DeleteItemFailure implements Action {
    readonly type = ListActionTypes.DeleteItemFailure;
}

export class SetDialogVisibility implements Action {
    readonly type = ListActionTypes.SetDialogVisibility;

    constructor(public payload: boolean) { } // depends on this value I show or hide dialog
}

export type VoyagePageActions = CreateVoyage
    | DeleteItem
    | DeleteItemSuccess
    | DeleteItemFailure
    | SetDialogVisibility;

list.effects.ts

    export class ListEffects {

    constructor(
        private actions$: Actions,
        private store: Store<fromStore.State>
    ) { }

    @Effect() DeleteItem$: Observable<Action> = this.actions$
        .pipe(
            ofType(ListActionTypes.DeleteItem),
            map((action: DeleteItem) => action.payload),
            // show dialog
            // wait for answer
            // send http request to delete item
            // delete item from store
        );
}

Ответы [ 2 ]

0 голосов
/ 04 июня 2019

Если вы рассуждаете по своему коду и поведению приложения, вы обнаружите, что у вас есть - два нажатия кнопки (или вы можете называть их действиями) - сначала открыть модальный режим, затем запустить метод Http или закрыть модальный режим. Между этими двумя действиями у вас есть состояние зависания - идентификатор элемента или другие данные. А состояние в NgRx живет в его хранилище, поэтому имеет смысл хранить его там, и тогда эти два действия легко отменить (щелчки кнопок).

list.component.ts

deleteItem(itemId: string) {
  this.store.dispatch(new fromStore.openModal({
    action: fromStore.DeleteItem,
    payload: itemId
  }));
}

your.reducer.ts

case fromStore.openModal:
  // add to the state

Confirm-dialog.component.ts

confirm$ = fromEvent(this.confirmBtn, 'click').pipe(mapTo(new fromStore.ModalAction()))
cancel$ = fromEvent(this.confirmBtn, 'click').pipe(mapTo(new fromStore.CloseModal()))

ngAfterViewInit() {
  merge(this.confirm$, this.cancel$).pipe(take(1)).subscribe()
}

list.effects.ts

@Effect() DeleteItem$: Observable<Action> = this.actions$
    .pipe(
        ofType(SomeActionTypes.ModalAction),
        mergeMap(() => {
          return this.store.select(state => state.selectModalState).pipe(
            map({action, payload}) => {
              return {
                type: action,
                payload
              };
            })
          )
        )

Затем вы просто строите все другие действия, например DeleteItem в эффектах. Также ваш модал теперь может работать с любым действием, которое вы ему предоставляете - DeleteItem, UpdateItem и т. Д.

обратите внимание, что этот код предназначен только для визуализации. Я не пробовал, так что вам придется работать с именами, синтаксисом и т. Д.

0 голосов
/ 04 июня 2019

Я бы сказал, что диалог не имеет никакого отношения к управлению состоянием.Не все должно быть обработано эффектом.

В случае использования углового материала я бы использовал службу диалога непосредственно в вашем ListComponent для отображения диалога, а затем ждал либо подтверждения, либо отмены.

const dialogRef = this.dialog.open(RemoveProjectDialogComponent, {
      data: project
    });

    dialogRef.afterClosed().subscribe(async result => {
      // if result is set, it means the user clicked confirm
      if (result) {
        await this.projectService.remove(this.project.id);
        this.snackBar.open('Project removed');
        this.router.navigate(['/']);
      }
    });
...