Multiple Undo using NgRx

Suresh Nagar
3 min readSep 2, 2019

This article talks about implementing multiple Undo functionality using NgRx.

Though in modern application most of the times any operation performed by user like add/edit/delete etc is immediately persisted at the server, there are many cases where we don’t want to save the state to server as soon as the action is performed.

Let’s assume we have to create a grid where user can add/edit/delete records but data is persisted in one go and we want to give user a functionality to “Undo” his actions just like text editors.

NgRx Angular Application

We start by creating an Angular application with NgRx. Let’s say we have a list of orders where user can add multiple orders and hit save at the end. We start by defining state as

export interface State {   ordersState: OrderState;   undoStack: OrderState[];}

and action and reducers to Add/Delete Orders in the state.

Actions to add/delete orders
Reducers to add/delete orders

We are all set with the basic application, let’s see how we can implement undo. As you must have noticed we have added an extra slice in the state as “undoStack”. This slice holds a stack of undo states. We push the previous orders state to the state before making a change.

This can be achieved with a higher level reducer or “reducerEnhancer” but NgRx provides another to implement this.

Meta Reducers

We create a “undoMetaReducer” and configure in our application. Meta reducers are hooks in the action-reducer pipeline and allow us to pre-process any action before it is handled by the application reducer. Also the full state is passed to metaReducers instead of the particular state slice, so metaReducers can handle any action and modify any slice of the state. We configure our meta reducer as below:

The above undoMetaReducer kicks in before any action is performed by the application reducer. The undoMetaReducer pushes the previous orderState to the stack and then delegates the action to the application reducer.

When “Undo” action is dispatched by the application, on click of undo button on UI, undoMetaReducer intercepts it and simply pops the last state from undoStack and returns. Note that we don’t pass the undo action to the application reducer as none of the main application reducer need to handle it.

We can also create a selector on the undo stack state slice and disable the undo button if the stack is empty.

As we are only talking about “Undo” there is no need to talk about views, stores and selectors etc.

Checkout project source code at https://github.com/nagarsuresh/ngrx-multiple-undo and demo at https://nagarsuresh.github.io/ngrx-multiple-undo/ngrx-multiple-undo/ . This project uses VMware Clarity for DataGrid and dark theme.

--

--