Made a custom calculate button but why it's not putting the value into the field

Question / Problem
Why isn't a value being set in "hour", even though the code I wrote looks fine?

Current Situation

I am making a todo App. It is supposed to be like...

  • click button
  • calculate "start time" and "end time"
  • writes the time difference into "hour"

I also added the "dayjs" CDN.
However, after clicking the button, nothing happens in the hour field.

Code / Attempts

(() => {
  const SPACE_ELEMENT_ID = 'space'; //

  kintone.events.on('app.record.detail.show', (event) => {
    const el = kintone.app.record.getSpaceElement(SPACE_ELEMENT_ID);
    if (!el || document.getElementById('calc-time-button')) {
      return event;
    }
    const button = document.createElement('button');
    button.id = 'calc-time-button';
    button.textContent = 'Calculate Time';
    button.style.margin = '4px';
    el.appendChild(button);

    button.addEventListener('click', () => {
      const record = kintone.app.record.get();
      const rows = record.record.to_do_table.value;
      const today = dayjs().format('YYYY-MM-DD');

      rows.forEach((row) => {
        const start = row.value.start_time.value;
        const end = row.value.end_time.value;
        if (!start || !end) return;

        const s = dayjs(`${today}T${start}`);
        const e = dayjs(`${today}T${end}`);
        const hours = e.diff(s, 'minute') / 60;

        row.value.Number.value = String(hours);
      });
      kintone.app.record.set(record);
    });
    return event;
  });
})();

Hello @kokonuts

Welcome to the community!

I was able to reproduce the behavior with a similar app.
The issue appears to be with the following part of your script:

kintone.app.record.set(record);

Your button is being added on the Record Details page using the app.record.detail.show event. While you can retrieve the record data and calculate the time difference there, kintone.app.record.set() does not save those changes back to the record from the Record Details page.

If you want to calculate the time when the button is clicked and save the result to the table, you can use the Update Record REST API instead.

For example:

(() => {
  'use strict';

  const SPACE_ELEMENT_ID = 'space';

  kintone.events.on('app.record.detail.show', (event) => {
    const el = kintone.app.record.getSpaceElement(SPACE_ELEMENT_ID);

    if (!el || document.getElementById('calc-time-button')) {
      return event;
    }

    const button = document.createElement('button');
    button.id = 'calc-time-button';
    button.textContent = 'Calculate Time';
    button.style.margin = '4px';
    el.appendChild(button);

    button.addEventListener('click', async () => {
      const rows = event.record.to_do_table.value;
      const today = dayjs().format('YYYY-MM-DD');

      const updatedRows = rows.map((row) => {
        const start = row.value.start_time.value;
        const end = row.value.end_time.value;

        if (!start || !end) {
          return {
            id: row.id
          };
        }

        const s = dayjs(`${today}T${start}`);
        const e = dayjs(`${today}T${end}`);
        const hours = e.diff(s, 'minute') / 60;

        return {
          id: row.id,
          value: {
            Number: {
              value: String(hours)
            }
          }
        };
      });

      const params = {
        app: event.appId,
        id: event.recordId,
        record: {
          to_do_table: {
            value: updatedRows
          }
        }
      };

      try {
        await kintone.api(
          kintone.api.url('/k/v1/record.json', true),
          'PUT',
          params
        );

        location.reload();
      } catch (error) {
        console.error(error);
        alert('Failed to update the record.');
      }
    });

    return event;
  });
})();

This calculates the time difference, updates the Number field in each applicable table row through the Update Record REST API, and reloads the page so the saved values are displayed.

Also, this sample assumes that the start and end times are on the same day. If a task can span midnight, additional logic would be needed to handle that case.

I hope this helps!