Add undo & redo functionality in your APP

halo! Opps I spelled it wrong. Let me Ctrl+z this. Ohh wait your app doesn’t support undo and redo, what a shame 🙁 Okay in this article lets fix that.
But instead of working with a big and complex project lets use this simple class that does some calc…


This content originally appeared on DEV Community and was authored by Shuvo

halo! Opps I spelled it wrong. Let me Ctrl+z this. Ohh wait your app doesn't support undo and redo, what a shame :( Okay in this article lets fix that.
But instead of working with a big and complex project lets use this simple class that does some calculations.

class Calculate {
    constructor(initialValue){
        this.value = initialValue
    }
    add(val){
        this.value += val
    }
    sub(val){
        this.value -= val
    }
    mul(val){
        this.value *= val
    }
    div(val){
        this.value /= val
    }
}


const num = new Calculate(0)
num.add(10) // Value: 0 + 10 = 10
num.add(20) // Value: 10 + 20 = 30
num.mul(2) // Value: 30 * 2 = 60
num.sub(100) // Value: 60 - 100 = -40
console.log(num.value) // Output: -40

Now we want to add undo and redo functionality to our class.
So basically we should be able to so this

const num = new Calculate(0)
num.add(10)
num.add(20)
num.mul(2)
num.sub(100)

num.undo()
num.undo()
num.redo()

console.log(num.value) // Expected output: 60

Okay so first we will create another class called Executor that will have a execute function that take two functions:

  1. Function that does the indented operation
  2. Function that undo the operation
class Executor {
    constructor(){
        // Stores the undo functions
        this.undoQueue = []
        // Stores the redo functions
        this.redoQueue = []
    }
    execute(fn, undoFn){
        fn()
        this.undoQueue.push(() => {
            undoFn()
            // The redo will be added to queue only after the undo is executed
            this.redoQueue.push(fn) // calling fn after undoFn will be redoing the same operation
        })
    }
    undo(){
        if(this.undoQueue.length > 0){
            this.undoQueue.pop()()
        }
    }
    redo(){
        if(this.redoQueue.length > 0){
            this.redoQueue.pop()()
        }
    }
}

So now lets use the Executor in our Calculate class.

class Calculate {
    constructor(initialValue){
        this.value = initialValue
        this.executor = new Executor()
    }
    add(val){
        this.executor.execute(
            () => this.value += val, //Function to execute
            () => this.value -= val //Function to undo
        )
    }
    sub(val){
        this.executor.execute(
            () => this.value -= val, //Function to execute
            () => this.value += val //Function to undo
        )
    }
    mul(val){
        this.executor.execute(
            () => this.value *= val, //Function to execute
            () => this.value /= val //Function to undo
        )
    }
    div(val){
        this.executor.execute(
            () => this.value /= val, //Function to execute
            () => this.value *= val //Function to undo
        )
    }
    redo(){
        this.executor.redo()
    }
    undo(){
        this.executor.undo()
    }
}

So now we can simply use num.undo() to undo the operation and num.redo() to redo it.
So here is the full code

class Calculate {
    constructor(initialValue){
        this.value = initialValue
        this.executor = new Executor()
    }
    add(val){
        this.executor.execute(
            () => this.value += val,
            () => this.value -= val
        )
    }
    sub(val){
        this.executor.execute(
            () => this.value -= val,
            () => this.value += val
        )
    }
    mul(val){
        this.executor.execute(
            () => this.value *= val,
            () => this.value /= val
        )
    }
    div(val){
        this.executor.execute(
            () => this.value /= val,
            () => this.value *= val
        )
    }
    redo(){
        this.executor.redo()
    }
    undo(){
        this.executor.undo()
    }
}

class Executor {
    constructor(){
        this.undoQueue = []
        this.redoQueue = []
    }
    execute(fn, undoFn){
        fn()
        this.undoQueue.push(() => {
            undoFn()
            this.redoQueue.push(fn)
        })
    }
    undo(){
        if(this.undoQueue.length > 0){
            this.undoQueue.pop()()
        }
    }
    redo(){
        if(this.redoQueue.length > 0){
            this.redoQueue.pop()()
        }
    }
}

const num = new Calculate(0)
num.add(10)
num.add(20)
num.mul(2)
num.sub(100)

num.undo()
num.undo()
num.redo()

console.log(num.value) // Output: 60

Make sure you checkout my other articles and YouTube channel

.ltag__user__id__728097 .follow-action-button { background-color: #000000 !important; color: #ffffff !important; border-color: #000000 !important; }
0shuvo0 image

Was it helpful? Support me on Patreon

Patreon Logo


This content originally appeared on DEV Community and was authored by Shuvo


Print Share Comment Cite Upload Translate Updates
APA

Shuvo | Sciencx (2021-11-14T12:56:21+00:00) Add undo & redo functionality in your APP. Retrieved from https://www.scien.cx/2021/11/14/add-undo-redo-functionality-in-your-app/

MLA
" » Add undo & redo functionality in your APP." Shuvo | Sciencx - Sunday November 14, 2021, https://www.scien.cx/2021/11/14/add-undo-redo-functionality-in-your-app/
HARVARD
Shuvo | Sciencx Sunday November 14, 2021 » Add undo & redo functionality in your APP., viewed ,<https://www.scien.cx/2021/11/14/add-undo-redo-functionality-in-your-app/>
VANCOUVER
Shuvo | Sciencx - » Add undo & redo functionality in your APP. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/11/14/add-undo-redo-functionality-in-your-app/
CHICAGO
" » Add undo & redo functionality in your APP." Shuvo | Sciencx - Accessed . https://www.scien.cx/2021/11/14/add-undo-redo-functionality-in-your-app/
IEEE
" » Add undo & redo functionality in your APP." Shuvo | Sciencx [Online]. Available: https://www.scien.cx/2021/11/14/add-undo-redo-functionality-in-your-app/. [Accessed: ]
rf:citation
» Add undo & redo functionality in your APP | Shuvo | Sciencx | https://www.scien.cx/2021/11/14/add-undo-redo-functionality-in-your-app/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.