Our flexible Kanban board for managing tasks with drag drop


Post by jasonlunsford »

Dear Support,

I hope this will be easier once we have JSX support in TaskBoard. But for now I would like to test the ability to capture the click event on CHILDREN elements (like a button for example), within a Task card. Below is my render logic. We need to configure the card to allow the button to capture this event.

Any ideas?

  const Test = (record) => {
    return `<div class="card">
      <div class="type-row">
        <span>${record.lookupActionType}</span>
      </div>
      <div class="title-row">
        <span class="title">${record.name}</span>
      </div>
      <div class="status-row">
        <span>${record.lookupActionStatus}</span>
        <button id="target">${record.priority}</button>
      </div>
    </div>`;
  };

  const taskRenderer = useCallback((params) => {
    const record = params.taskRecord.data;

params.cardConfig.children.body = {
  html: Test(record),
};

  }, []);
  
const onModelChange = (payload) => { // do something when the model changes const button = document.getElementById("target"); button?.addEventListener("click", (event) => { console.log('button fired'); }); };
return ( <BryntumProjectModel ref={projectRef} events={taskData} onChange={onModelChange} /> );

Post by marcio »

Hey Jason,

I didn't understand, why can't you add an onclick handler to the button?

<button id="target" onclick="myFunction()">${record.priority}</button>

What do you want to process in that click handler? Can you provide more context?

Best regards,
Márcio


Post by jasonlunsford »

HI Marcio,

Great questions. So it turns out:

<button id="target" onclick="myFunction()">${record.priority}</button>

Does not work properly, probably because it is an HTML template within a React component. I had to add a click event programmatically.

What I am trying to do is to figure out how to capture click events on child elements so that we can do interesting things if the user clicks on the Card Header or on a button we place within the Card (just to give some examples). We still want to capture click events on the Card if the user clicks in "empty areas" of the Card.

Does this make sense?


Post by jasonlunsford »

Marcio,

I figured out a way to do this. My code was close, I just needed to add a useCallback method to the click event. This works - but would love to know if there's a better way!

Edit: hoping I can do this in a cleaner way once JSX components are supported in Task Cards.

  const onClickEvent = useCallback((event) => {
    console.log('event from button: ', event);
  }, []);

  const onModelChange = (payload) => {
    // do something when the model changes
    const buttons = document.querySelectorAll(".target");

buttons.forEach((button) => {
  setTimeout(() => {
    button.addEventListener('click', onClickEvent);
  }, 100);
});
  };

Post by marcio »

Hey Jason,

That looks ok, but why are you using a setTimeout?

Besides that, you can use event delegation to optimize and have only one listener to handle clicks instead of one for each card (which could be a lot)

// inside onModelChange replace with this
// do something when the model changes
   const taskboard = document.querySelector(".b-taskboard");
    taskboard.addEventListener("click", handleClick);

and inside the click handler, you can put

const handleClick = (ev) => {
    if(ev.target.tagName === 'BUTTON') {
        console.log("button was clicked")
    }
  };

Best regards,
Márcio


Post by jasonlunsford »

Marcio,

The setTimout was there to avoid a race condition between DOM elements getting painted and associated listeners being attached. However your code is much better and works exactly as expected. Thank you!


Post Reply