Can't set property to all cells of one table in the doc with more than one tables

Hi, would be really glad if someone told me how to handle the situation. Many thanks in advance…!

[situation]

I’m trying to set property to all cells of one table. (Please assume the doc has more than one tables.) But I’ve never been able to find the way doing so now.

I set a command to my custom table cell as below, and call the command when the bubble menu is clicked with the focus on a cell of the targeted table.

// In the extension of TableCell...
addCommands() {
  return {
    ...this.parent?.(),
    setBorderStyleToAllTableCells: (tableNode, borderStyle) => ({ tr }) => {
      tableNode.descendants((node, pos) => {
        if (node.type.name === 'tableCell') {
          tr.setNodeMarkup(pos, null, {
            borderStyle: 'border-none',
          })
        }
      })
      return true
    },
  }
}

///////////

// When the bubble menu is clicked with the focus to a cell of the targeted table...
onClick={(borderStyle) => {
const tableNode = findParentNode(
      ({ type }) => type.name === 'table'
    )(editor.state.selection)

    if (tableNode?.node) {
      editor.commands.setAllTableCellsBorderStyle(
        tableNode?.node,
        'none'
      )
    }

    onSetSubContent(null) // just close the bubble menu
}}

[problem]

But that doesn’t work, because it seems that, in the method setBorderStyleToAllTableCells, the method descendants gives pos relative to the parent node while the method setNodeMarkup recognizes the given pos as absolute pos (i.e. pos relative to the doc). I noticed it when debugging.

I also tried to add the pos of the table cell as the offset, but neither did it work…(i couldn’t clarify the reason)

// in setBorderStyleToAllTableCells
const getNodePos = (node) => {
    let pos = -1
    tr.doc.forEach((childNode, _pos) => {
      if (childNode.eq(node)) {
        pos = _pos
      }
    })
    return pos
}
const tablePos = getNodePos(tableNode)
tableNode.descendants((node, pos) => {
  if (node.type.name === 'tableCell') {
    tr.setNodeMarkup(pos + tablePos, null, {
      borderStyle: 'border-none',
    })
  }
})

[additional info]

I found a similar post here.

But it didn’t work.

The problem is that, in my case, the doc has more than one tables. That means it’s not helpful to iterate all nodes in the doc and set property if the node is ‘table_cell’ as introduced in the above post.

really looking forward to someone’s great help…many thanks!

You can use tr.doc.nodesBetween(tablePos, tablePos + tableNodeSize, (node, pos) => { // your code... })

1 Like

Hi shinTSY,

That WORKS!! We highly appreciate your prompt response…!!!

For those who have the same situation, the below is where we reached finally. just FYI.

// In the extension of TableCell...
addCommands() {
    return {
      ...this.parent?.(),
      setBorderStyleToAllTableCells: (borderStyle) => ({ tr }) => {
        const tableNode = findParentNode(({ type }) => type.name === 'table')(
          this.editor.state.selection
        )
        const getNodePos = (node: Node) => {
          let pos = -1
          tr.doc.forEach((childNode, _pos) => {
            if (childNode.eq(node)) {
              pos = _pos
            }
          })
          return pos
        }
        const tablePos = getNodePos(tableNode?.node)

        tr.doc.nodesBetween(
          tablePos,
          tablePos + tableNode?.node.nodeSize,
          (node, pos) => {
            if (node.type.name === 'tableCell') {
              tr.setNodeMarkup(pos, null, {
                borderStyle: `${borderStyle}`,
              })
            }
          }
        )
        return true
      },
    }
  },

///////////

// When the bubble menu is clicked with the focus to a cell of the targeted table...
onClick={(borderStyle) => {
      editor.commands.setBorderStyleToAllTableCells(borderStyle)
      onSetSubContent(null)
}}

Many thanks, shinTSY!!

You’re very welcome. HAHAHA :laughing:

Also note that using node object identity like this (getNodePos) is very error-prone—it is valid for a the same node object to occur multiple times in the document, and changes to a node’s content will replace it with another object.

Thanks for noting that, marijn!! I got it. So, in this case, could you please also tell me what you think is the best alternative?

You’ll have to track nodes by position, not by object.

ok…but i couldn’t find the way getting the position of the table of the selected cell…

So how should i get the position of the table from the focus on its cell? is there any function returning the position of the node…? :thinking: