Refreshing a modal window when a button is clicked

Hello everyone! I have a task when clicking on the button “button_1” to remove buttons from the open modal window and fill it with new buttons. My code with the current modal window and buttons is below. How can I achieve the result? I did not find something similar in the documentation Rocket.Chat Developer

import {
    IAppAccessors,
    IConfigurationExtend,
    ILogger,
    IRead,
    IModify
} from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { ISlashCommand, SlashCommandContext } from "@rocket.chat/apps-engine/definition/slashcommands";
import { UIKitSurfaceType } from "@rocket.chat/apps-engine/definition/uikit";


export class CyApp extends App {
    constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
        super(info, logger, accessors);
    }

    protected async extendConfiguration(configuration: IConfigurationExtend): Promise<void> {
        await configuration.slashCommands.provideSlashCommand(new OpenModalCommand(this));
    }
}

class OpenModalCommand implements ISlashCommand {
    public command = 'score';
    public i18nParamsExample = 'slashcommand_params';
    public i18nDescription = 'slashcommand_description';
    public providesPreview = false;

    constructor(private readonly app: App) {}

    public async executor(
        context: SlashCommandContext,
        _read: IRead,
        modify: IModify
    ): Promise<void> {
        
        const block = modify.getCreator().getBlockBuilder();

        block.addSectionBlock({
            blockId: 'section_1',
            text: block.newPlainTextObject('Нажми на интересующий вопрос', true),
        });


        const space_3 = '\u2800\u2800\u2800';
        const space_4 = '\u2800\u2800\u2800\u2800';
        const space_5 = '\u2800\u2800\u2800\u2800\u2800';
        const space_7 = '\u2800\u2800\u2800\u2800\u2800\u2800\u2800';
        const space_8 = '\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800';

        block.addActionsBlock({
            blockId: 'buttons_block',
            elements: [
                block.newButtonElement({
                    actionId: 'button_1',
                    text: block.newPlainTextObject(`${space_5}Text 1${space_5}`),
                    value: 'btn1',
                    style: undefined,
                }),
                block.newButtonElement({
                    actionId: 'button_2',
                    text: block.newPlainTextObject(`${space_5}Text 2${space_5}`),
                    value: 'btn2',
                    style: undefined,
                }),
                block.newButtonElement({
                    actionId: 'button_3',
                    text: block.newPlainTextObject(`${space_4}Text 3${space_4}`),
                    value: 'btn3',
                    style: undefined,
                    url: 'https:
                }),
            ],
        });

        block.addActionsBlock({
            blockId: 'buttons_block',
            elements: [
                block.newButtonElement({
                    actionId: 'button_4',
                    text: block.newPlainTextObject(`${space_7}Text 4${space_8}`),
                    value: 'btn4',
                    style: undefined,
                }),
                block.newButtonElement({
                    actionId: 'button_5',
                    text: block.newPlainTextObject(`${space_3}Text 5${space_4}`),
                    value: 'btn5',
                    style: undefined,
                    url: 'https:
                }),
                block.newButtonElement({
                    actionId: 'button_6',
                    text: block.newPlainTextObject(`${space_7}Text 6${space_8}`),
                    value: 'btn6',
                    style: undefined,
                    url: 'https:
                }),
            ],
        });

        await modify.getUiController().openSurfaceView(
            {
                id: 'modal-id',
                type: UIKitSurfaceType.MODAL,
                title: {
                    text: 'SCORE',
                    type: 'plain_text'
                },
                blocks: block.getBlocks(),
            },
            { triggerId: context.getTriggerId()! },
            context.getSender()
        );
    }
}
=

Try this if it help: handle the button’s action event and then call modify.getUiController().updateSurfaceView() with the new blocks.

Implement a handler for button clicks (action events).
When button_1 is clicked, build a new block layout with the new buttons.
Use updateSurfaceView() to replace the modal content.

eg:

public async executeActionHandler(context: UIKitInteractionContext, read: IRead, modify: IModify, http: IHttp, persistence: IPersistence): Promise {
const actionId = context.getInteractionData().actionId;

if (actionId === 'button_1') {
    const block = modify.getCreator().getBlockBuilder();

    // Build new buttons or other blocks here
    block.addSectionBlock({
        text: block.newPlainTextObject('New buttons after button_1 clicked'),
    });

    block.addActionsBlock({
        elements: [
            block.newButtonElement({
                actionId: 'new_button_1',
                text: block.newPlainTextObject('New Button 1'),
                value: 'new_btn1',
            }),
            // add more buttons as needed
        ],
    });

    // Update the modal with new blocks
    await modify.getUiController().updateSurfaceView(
        {
            id: 'modal-id',
            type: UIKitSurfaceType.MODAL,
            title: {
                text: 'Updated SCORE',
                type: 'plain_text',
            },
            blocks: block.getBlocks(),
        },
        { triggerId: context.getInteractionData().triggerId },
        context.getInteractionData().user.id
    );

    return { success: true };
}

return { success: false };

}

Best,
[Edit - No ad links]

1 Like

Thanks, I finally managed to achieve the effect this way. Here is the working code:

import {
  IAppAccessors,
  IConfigurationExtend,
  ILogger,
  IRead,
  IModify,
  IHttp,
  IPersistence,
} from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { ISlashCommand, SlashCommandContext } from '@rocket.chat/apps-engine/definition/slashcommands';
import {
  IUIKitInteractionHandler,
  UIKitBlockInteractionContext,
  UIKitSurfaceType,
} from '@rocket.chat/apps-engine/definition/uikit';

export class CyApp extends App implements IUIKitInteractionHandler {
  constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
    super(info, logger, accessors);
  }

  protected async extendConfiguration(configuration: IConfigurationExtend): Promise<void> {
    await configuration.slashCommands.provideSlashCommand(new OpenModalCommand(this));
  }

  // 1) Handle button clicks from UIKit blocks
  public async executeBlockActionHandler(
    context: UIKitBlockInteractionContext,
    read: IRead,
    http: IHttp,
    persistence: IPersistence,
    modify: IModify,
  ) {
    const data = context.getInteractionData();

    if (data.actionId === 'button_1') {
      const bb = modify.getCreator().getBlockBuilder();

      bb.addSectionBlock({
        blockId: 'new_section',
        text: bb.newPlainTextObject('New buttons after button_1 clicked'),
      });

      bb.addActionsBlock({
        blockId: 'new_buttons_row',
        elements: [
          bb.newButtonElement({
            actionId: 'new_button_1',
            text: bb.newPlainTextObject('New Button 1'),
            value: 'new_btn1',
          }),
          bb.newButtonElement({
            actionId: 'new_button_2',
            text: bb.newPlainTextObject('New Button 2'),
            value: 'new_btn2',
          }),
        ],
      });

      // 2) Update the *same* modal (same id) with the new blocks
      await modify.getUiController().updateSurfaceView(
        {
          id: 'modal-id',                              // must match the id used when opening
          type: UIKitSurfaceType.MODAL,
          title: { type: 'plain_text', text: 'Updated SCORE' },
          blocks: bb.getBlocks(),
        },
        { triggerId: data.triggerId! },                // must pass current triggerId
        data.user,                                     // the user who clicked
      );

      // Return a successful UIKit response
      return context.getInteractionResponder().successResponse();
    }

    // Default: do nothing special
    return context.getInteractionResponder().successResponse();
  }
}

class OpenModalCommand implements ISlashCommand {
  public command = 'score';
  public i18nParamsExample = 'slashcommand_params';
  public i18nDescription = 'slashcommand_description';
  public providesPreview = false;

  constructor(private readonly app: App) {}

  public async executor(context: SlashCommandContext, _read: IRead, modify: IModify): Promise<void> {
    const bb = modify.getCreator().getBlockBuilder();

    bb.addSectionBlock({
      blockId: 'section_1',
      text: bb.newPlainTextObject('Нажми на интересующий вопрос', true),
    });

    bb.addActionsBlock({
      blockId: 'buttons_row_1',
      elements: [
        bb.newButtonElement({ actionId: 'button_1', text: bb.newPlainTextObject('Text 1'), value: 'btn1' }),
        bb.newButtonElement({ actionId: 'button_2', text: bb.newPlainTextObject('Text 2'), value: 'btn2' }),
        bb.newButtonElement({ actionId: 'button_3', text: bb.newPlainTextObject('Text 3'), value: 'btn3' }),
      ],
    });

    bb.addActionsBlock({
      blockId: 'buttons_row_2',
      elements: [
        bb.newButtonElement({ actionId: 'button_4', text: bb.newPlainTextObject('Text 4'), value: 'btn4' }),
        bb.newButtonElement({ actionId: 'button_5', text: bb.newPlainTextObject('Text 5'), value: 'btn5' }),
        bb.newButtonElement({ actionId: 'button_6', text: bb.newPlainTextObject('Text 6'), value: 'btn6' }),
      ],
    });

    await modify.getUiController().openSurfaceView(
      {
        id: 'modal-id',
        type: UIKitSurfaceType.MODAL,
        title: { text: 'SCORE', type: 'plain_text' },
        blocks: bb.getBlocks(),
      },
      { triggerId: context.getTriggerId()! },
      context.getSender(),
    );
  }
}