Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update event not triggered on checkbox when onReadOnlyChecked returns true and editable is false #3676

Open
1 of 2 tasks
deterralba opened this issue Jan 30, 2023 · 8 comments
Labels
Type: Bug The issue or pullrequest is related to a bug

Comments

@deterralba
Copy link

What’s the bug you are facing?

Hello & thank you for this awesome lib 👍

The 'update' event is not not triggered on checkbox elements when the editor is not in its editable state but onReadOnlyChecked returns true (tested with react)

Which browser was this experienced in? Are any special extensions installed?

latest firefox version on ubuntu

How can we reproduce the bug on our side?

with this sandbox : https://codesandbox.io/s/update-not-trigger-on-checkbox-when-editable-is-false-v87v22?file=/src/App.js:468-485
you can see in the console that the update event is not trigger when editable is false, but it is when editable is true.

Can you provide a CodeSandbox?

here https://codesandbox.io/s/update-not-trigger-on-checkbox-when-editable-is-false-v87v22?file=/src/App.js:468-485

What did you expect to happen?

I would expect the update event to be trigger when the checkbox state changes, even if editable is set to false. Is this is not a bug but a API design choice, do I have the ability to trigger manually an update event?

Anything to add? (optional)

No response

Did you update your dependencies?

  • Yes, I’ve updated my dependencies to use the latest version of all packages.

Are you sponsoring us?

  • Yes, I’m a sponsor. 💖
@deterralba deterralba added the Type: Bug The issue or pullrequest is related to a bug label Jan 30, 2023
@parsch
Copy link

parsch commented Mar 14, 2023

We're struggling with the exact same issue while trying to save the contents of a non-editable editor via an API call. (And yes, we're sponsors.)

@parsch
Copy link

parsch commented Mar 16, 2023

We're not able to save updated contents (to a DB) because the contents are not updated when toggling a TaskItem (with onReadOnlyChecked configured) in a non-editable editor. I've got no idea how else we could get updated contents.

I've forked/updated the CodeSandbox of @deterralba (thx) to better illustrate the problem we're facing: https://codesandbox.io/s/tiptap-taskitem-content-not-updated-when-not-editable-tnsbkx?file=/src/App.js

@yenche123
Copy link

I found the same issue and tried to use the first parameter node of onReadOnlyChecked to find out which taskItem changed, but there seemed to be no way to know

@parsch
Copy link

parsch commented Apr 26, 2023

We're not able to save updated contents (to a DB) because the contents are not updated when toggling a TaskItem (with onReadOnlyChecked configured) in a non-editable editor. I've got no idea how else we could get updated contents.

I've forked/updated the CodeSandbox of @deterralba (thx) to better illustrate the problem we're facing: https://codesandbox.io/s/tiptap-taskitem-content-not-updated-when-not-editable-tnsbkx?file=/src/App.js

I updated the Sandbox to Tiptap 2.0.3, the problem still exists. Any chance that a team member looks into this or can give a hint?

@bdbch bdbch added this to Tiptap Aug 4, 2023
@github-project-automation github-project-automation bot moved this to Triage open in Tiptap Aug 4, 2023
@penghuili
Copy link

penghuili commented Aug 10, 2023

I faced the same problem, in the end i used patch-package to changed the source code, i am using @tiptap/extension-task-item@2.0.4, this is the change:

diff --git a/node_modules/@tiptap/extension-task-item/dist/index.js b/node_modules/@tiptap/extension-task-item/dist/index.js
index 39c698c..3001751 100644
--- a/node_modules/@tiptap/extension-task-item/dist/index.js
+++ b/node_modules/@tiptap/extension-task-item/dist/index.js
@@ -100,9 +100,17 @@ const TaskItem = Node.create({
                 }
                 if (!editor.isEditable && this.options.onReadOnlyChecked) {
                     // Reset state if onReadOnlyChecked returns false
-                    if (!this.options.onReadOnlyChecked(node, checked)) {
-                        checkbox.checked = !checkbox.checked;
+                    if (checkbox.checked) {
+                        checkbox.setAttribute('checked', 'checked');
+                    } else {
+                        checkbox.removeAttribute('checked');
                     }
+                    listItem.dataset.checked = checkbox.checked;
+                    const editorDom = editor.view.dom;
+                    Array.from(editorDom.querySelectorAll('li[data-checked]')).forEach(item => {
+                        item.dataset.type = "taskItem";
+                    });
+                    this.options.onReadOnlyChecked(node, checked, editorDom.innerHTML);
                 }
             });
             Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {

the original code only passes node and checked to onReadOnlyChecked, what i did is,

  1. firstly update DOM of list-item and the input to reflect the new checked value;
  2. then add "data-type=taskItem" to all li[data-checked] element (for some reason, if i don't do this, all li won't have data-type, then the checkbox won't be checked);
  3. then get the whole html from editor.view.dom.innerHTML, and pass it to the third param. (i tried to get the whole html from editor.getHTML(), but it doesn't work, seems its value is not updated at this moment.)

i also ignored the return value, if there is a onReadOnlyChecked, i will just update the checked value.

@mgtcampbell
Copy link

FWIW here's another solution that works for me... although still feels quite hacky

NOTE 1: I'm working in Vue but imagine the approach is similar for any other JS
NOTE 2: This is based off using the UniqueID extension so that each node has an ID to scan for

Quick rundown of the approach:

  1. Firstly, I update the actual DOM so that all my styling for checked/unchecked works correctly straight away
  2. Then instead of trying to interact with the editor in it's non-editable state (which seemed very hit and miss), I actually update the value that I have stored in my Vue component. I used my "stringified" version of the JSON instead of the actual JSON object so that I didn't have to use a costly recursive search through the JSON object to find the matching block.
  3. Then I can use that stringified JSON to update the actual JSON value and also the editor value (not even sure that last part is needed but wanted to make sure it's updated say if then the user switches into full edit mode without reloading the page)
  4. Lastly I just check if the value has actually changed, and then emit an event from my Tiptap component to tell it's parent that the value should be updated in the database, and then handle that "quietly" so the user doesn't really notice that the data has been passed back and forth between the database.

Welcome any suggestions or corrections... as I said this still feels quite hacky but might help someone.

TaskItem.configure({
  nested: true,
  onReadOnlyChecked: (node, checked) => {
    // get the dom from the editor and then find the node by block id
    let editorDom = editor.value.view.dom
    let nodeDom = editorDom.querySelector(`[data-blockid="${node.attrs.blockId}"]`)
    // change the data-checked attribute on the node to checked value
    nodeDom.setAttribute('data-checked', checked)
    // change the input checked value
    nodeDom.querySelector('input').setAttribute('checked', checked)
    // update the currentValueJSON by finding the node in the json string and replacing it with the new checked value
    currentValueJSON.value = currentValueJSON.value.replace(`"blockId":"${node.attrs.blockId}","checked":${!checked}`, `"blockId":"${node.attrs.blockId}","checked":${checked}`)
    // update the current value array
    currentValue.value = JSON.parse(currentValueJSON.value)
    // update the editor value based off the updated array
    editor.value.commands.setContent(currentValue.value, false)
    nextTick(() => {
      // check if the value has changed and if so then emit update:shouldSave
      if(JSON.stringify(currentValue.value) !== JSON.stringify(props.value)) {
        emit('update:shouldSaveQuietly')
      }
    })
    return true
  }
}),

Zyten added a commit to Zyten/wiki that referenced this issue Sep 14, 2023
Issue ueberdosis/tiptap#3676 means changes in View mode will not be saved
BreadGenie added a commit to frappe/wiki that referenced this issue Sep 20, 2023
* feat: add support for tiptap task-item

* fix: save state when task-item is updated in View mode

* fix: disable task-list checkbox in View mode

Issue ueberdosis/tiptap#3676 means changes in View mode will not be saved

* fix: mock tiptap edit mode for task-list

Will be made redundant once ueberdosis/tiptap#4044 is fixed

* style(task-item): minor style changes

* chore: format using prettier

---------

Co-authored-by: Bread Genie <msuhailbh07@gmail.com>
@kolaente
Copy link

This is still a problem in 2.1.13.

@kolaente
Copy link

Any chance to get this fixed? I'm currently pouring workaround over workaround to make this work, but I don't think that should be necessary, neither does it seem like doing that is maintainable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Bug The issue or pullrequest is related to a bug
Projects
Status: Triage open
Development

No branches or pull requests

6 participants