I would like to keep the Save Draft button disabled when there aren't changes on the document to save:
- Creating a new document
- The Save Draft button is disabled by default, you start typing and the button gets enabled, then oh! you change your mind and delete what you typed, in this case the Save Draft button is still enabled. If you leave the page at this point, you will receive a warning that there are unsaved data which can be a bit confusing, also you can click on Save Draft and save an empty row, it is not ideal to save empty rows and also to avoid api calls I guessed.
- When updating an existing document
- Again, the first state of the Save Draft button is disabled, then you start typing on any field, the button gets enabled, then you backspace or revert the value to how it was, the button is still enabled.
I just wanted to check first is this is something that can be currently done with the existing built-in fields options.
What a good catch!!!
I was also suffering from this issue. I hope it would be very appreciate someone who is talented in PayloadCMS would help fix this issue.
this isn't something that's possible right now - we could implement it, however, it would come with some performance drawbacks. basically, we would have to diff the whole document against its original shape every time a field is changed. that would potentially be costly
actually on second thought, maybe there is a better way to do this
Compare an md5 of the form state?
Hi, I understand! If it is a large document, checking for every field change will be heavy on performance. I've been playing a bit with this; I am thinking about comparing the states (like Dan’s idea) only on submit (for now) to avoid empty rows, unnecessary draft versions of the document and/or unnecessary api calls. I'm also thinking about adding a Go Back or Cancel button that when it's clicked will discard any changes and go back without the warning screen that there are unsaved changes.
oooo "Discard Changes" might be nice
You could diff each input field, only if it’s dirty. If an input hasn’t been touched, no need to diff it.
right - that's kinda what i'm thinking too
I almost got it working using getFields from useWatchForm which throws an object with the values of the current state and the initialValues, I'm creating two arrays to compare them. It's working but I need to improve how I'm shaping the arrays to reduce them as much as posible. I don't know what's the impact of using useWatchForm or useGetAllFields ()
I forgot to say that I don't know if this the best approach. But I'm just trying
I played over the weekend with this.
This document has 5 rich text fields, each of them has around 11,000 words.
Do you want to share your code or open a PR? We can work towards getting this into Payload for everyone.
Yes, definitely!. It needs more work and testing, I'll be more than happy to keep improving this with your help. It isn't perfect. I'm a junior dev and I just started learning typescript recently, so expect some mistakes . Let me document what I have done and then I'll share this.
wow, killer, would love to see how you did it
Hi, yes, I can explain how it works.
I started playing with this in the save-draft component, I found that I could import useWatchForm and get the fields data from it using getFields. Within the data from getFields, each field has a key
that represents the live value (or the value that changes when typing etc) and a key
that represents the initialValue, this initialValue doesn't change, making it easy to compare these two values for each field.
So, I create a function that takes getFields() as an object, the key value we want to filter, an array to add the filtered values. From this function we can get the two arrays, one with the hey
and one with
. I am still working on the way the arrays are shaped, so nothing is missed, the arrays are reduce into a single string using join and trim.
Then, these two arrays are compared every time a field change.
- The form re-renders every time a field change. It still feels fast but I don't know how it'll perform with very large documents.
Another approach as you @jmikrut and @TacticalSmoores thought about, would be to get from useWatchForm only the field is changing using getField, this function will require the path of the field which I haven't yet worked out how to do. I guess I have to add an event listener to get this path, some examples will be helpful. And then, comparing the values per field instead of comparing all the fields with arrays.
I will open a PR, I just want to move my function to a new file, and then using it in the save, save-draft and publish buttons
@Eustachio just saw you opened the PR! Thank you so much! I'll check it out as soon as I can.https://github.com/payloadcms/payload/pull/2390
Yes!!! You're welcome. I hope it works well. Please let me know if you have any questions. Cheers!
Get help straight from the Payload team with an Enterprise License.