Search code examples
node.jsbotframework

How can I set the list style to force prompts to be buttons?


I much prefer the look of buttons to a numbered list, but the default handling of prompt in waterfall dialog is to automatically change from buttons (default) to a numbered list after a certain length of content.

I'm currently implementing the prompt like this:

return await step.prompt(FOCUS_AREA_PROMPT, {
    prompt: 'Got it. Can you confirm the focus area this is for?',
    choices: ChoiceFactory.toChoices(FOCUS_AREAS)
});

I've tried adding a style attribute within this prompt, and also tried adding to the addDialogs line this.dialogs.add(new ChoicePrompt(FOCUS_AREA_PROMPT)); but nothing I have tried has modified the behavior of the options.

I've reviewed the ListStyle enum in the MS docs, but any method I've tried to add these in with has not made any difference. Is there any way to force buttons regardless of content length?


Solution

  • You can set up a choice prompt in the following manner to achieve the buttons look you are seeking. For reference, you can read more about forChannel here.

    Alter to match your needs.

    Hope of help!

    [edit]

    Updated below to represent the two ways a Choice Prompt can be assembled and how the value is output (via imBack). When using toChoices, the associated button value is returned in activity.text and in stepContext.result.value (as type Object). When using forChannel, the associated button value is returned in activity.text and in stepContext.result (as type String).

    As discussed in the comments, the button title length has a character limit however this is channel specific. When testing in Web Chat, the limit is 20 characters. Adjusting the FOCUS_AREAS "AI & Machine Learning" value (21 chars) to "AI/Machine Learning" (19 chars) results in the choices displaying as buttons and not a list.

    Option 1: using toChoices

    async choiceStep ( stepContext ) {
      const stepResult = stepContext.context.activity.text;
    
      const FOCUS_AREAS = [ 'Chatbots', 'RPA', 'Blockchain', 'AR/VR', 'AI/Machine Learning' ]
    
      if ( stepResult ) {
        return await stepContext.prompt( CHOICE_PROMPT, {
          prompt: 'Got it. Can you confirm the focus area this is for?',
          choices: ChoiceFactory.toChoices( FOCUS_AREAS )
        } );
      }
    }
    
    activity:
    { type: 'message',
      id: 'A50eelAPrFIHKv9XeCRm24-o|0000021',
      timestamp: 2019-09-25T20:34:30.562Z,
      serviceUrl: 'https://directline.botframework.com/',
      channelId: 'directline',
      from: [Object],
      conversation: [Object],
      recipient: [Object],
      textFormat: 'plain',
      locale: 'en-US',
      text: 'Chatbots',
      channelData: [Object] },
    info:
    { index: 1,
      options: {},
      reason: 'endCalled',
      result:
        { value: 'Chatbots', index: 0, score: 1, synonym: 'Chatbots' },
      values: { instanceId: 'c10ed437-77eb-4502-cd24-e89d4c5e45cf' },
      onNext: [AsyncFunction: onNext] }
    

    Option 2: using forChannel

    async choiceStep ( stepContext ) {
      const stepResult = stepContext.context.activity.text;
    
      if ( stepResult ) {
        const message = ChoiceFactory.forChannel(
          stepContext.context, [
            { value: 'Chatbots', action: { type: 'imBack', title: 'Chatbots', value: 'Chatbots' } },
            { value: 'RPA', action: { type: 'imBack', title: 'RPA', value: 'RPA' } },
            { value: 'Blockchain', action: { type: 'imBack', title: 'Blockchain', value: 'Blockchain' } },
            { value: 'AR/VR', action: { type: 'imBack', title: 'AR/VR', value: 'AR/VR' } },
            { value: 'AI/Machine Learning', action: { type: 'imBack', title: '', value: 'AI/Machine Learning' }, text: 'AI/Machine Learning' },
        ], `Which do you choose?`
        );
        await stepContext.context.sendActivity( message );
      }
      return { status: DialogTurnStatus.waiting };
    }
    
    activity:
    { type: 'message',
      id: 'Cw5xvHTv6RCDWf3kkyS3Ir-o|0000205',
      timestamp: 2019-09-25T20:21:30.320Z,
      serviceUrl: 'https://directline.botframework.com/',
      channelId: 'directline',
      from: [Object],
      conversation: [Object],
      recipient: [Object],
      textFormat: 'plain',
      locale: 'en-US',
      text: 'Chatbots',
      channelData: [Object] },
    info:
    { index: 1,
      options: {},
      reason: 'continueCalled',
      result: 'Chatbots',
      values: { instanceId: '4becefed-88d2-773e-6184-91456609a26a' },
      onNext: [AsyncFunction: onNext] }
    

    enter image description here