Skip to content
This repository was archived by the owner on Oct 23, 2021. It is now read-only.

Lab 3 ‐ Advanced Quick View Functionality

ms-nichoi edited this page Jun 8, 2021 · 2 revisions

Start with the HelloWorld ACE from Lab 2. The HelloWorld ACE displays either the count of total steps or one individual step at a time. Using the Quick view, the ACE can show a list of all the steps. Additionally, the ACE can show more details about a particular step if it's selected.

1 - Show all items in Quick view

Navigate to src/adaptiveCardExtensions/helloWorld/quickView/QuickView.ts.

import { IListItem } from '../HelloWorldAdaptiveCardExtension';

Update the Quick view data getter.

export interface IQuickViewData {
  items: IListItem[];
}
public get data(): IQuickViewData {
  return {
    items: this.state.items
  };
}

Update the Quick view template getter.

public get template(): ISPFxAdaptiveCard {
  return {
    $schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
    type: 'AdaptiveCard',
    version: '1.2',
    body: [
      {
        type: 'Container',
        $data: '${items}', // Bind each item to a template in `items`
        selectAction: { // Action to handle an item click
          type: 'Action.Submit',
          data: {
            /*
             * Define `id` inside of `data` since each item will
             * have the same `selectAction` and the `selectAction.id`
             * property has to be unique between all items.
             */
            id: 'selectAction',
            newIndex: '${$index}',
          }
        },
        separator: true,
        items: [ // The template for an item in `items`
          {
            type: 'TextBlock',
            text: '${title}',
            color: 'dark',
            weight: 'Bolder',
            size: 'large',
            wrap: true,
            maxLines: 1,
            spacing: 'None'
          },
          {
            type: 'TextBlock',
            text: '${description}',
            color: 'dark',
            wrap: true,
            size: 'medium',
            maxLines: 1,
            spacing: 'None'
          }
        ]
      }
    ]
  };
}

Build and launch the ACE in the hosted Workbench.

gulp serve -l --nobrowser

Once the code is being served, navigate to the hosted Workbench.

https://{tenant}.sharepoint.com/_layouts/15/workbench.aspx

Open the Toolbox and select your ACE. Click on the Card to open the Quick view.

Since the onAction handler has not been changed to handle the item click, clicking on an item does nothing.

2 - Create a new Quick view

Create a new file under the src/adaptiveCardExtensions/helloWorld/quickView folder named DetailedQuickView.ts.

import { BaseAdaptiveCardView, IActionArguments, ISPFxAdaptiveCard } from '@microsoft/sp-adaptive-card-extension-base';
import { IHelloWorldAdaptiveCardExtensionProps, IHelloWorldAdaptiveCardExtensionState } from '../HelloWorldAdaptiveCardExtension';

export interface IDetailedViewData {
  title: string;
  description: string;
  details: string;
}

export class DetailedView extends BaseAdaptiveCardView<
  IHelloWorldAdaptiveCardExtensionProps,
  IHelloWorldAdaptiveCardExtensionState,
  IDetailedViewData
> {
  public get data(): IDetailedViewData {
    const { description, title } = this.state.items[this.state.currentIndex];
    return {
      description,
      title,
      details: 'More details'
    };
  }

  public get template(): ISPFxAdaptiveCard {
    return {
      $schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
      type: 'AdaptiveCard',
      version: '1.2',
      body: [
        {
          type: 'ColumnSet',
          columns: [
            {
              type: 'Column',
              items: [
                {
                  type: 'TextBlock',
                  text: '${title}',
                  size: 'ExtraLarge'
                },
                {
                  type: 'TextBlock',
                  text: '${description}',
                  size: 'Medium'
                }
              ]
            },
            {
              type: 'Column',
              style: 'emphasis',
              items: [
                {
                  type: 'TextBlock',
                  text: '${details}',
                  weight: 'Lighter'
                }
              ]
            }
          ]
        },
        {
          type: 'ActionSet',
          actions: [
            {
              type: 'Action.Submit',
              title: 'Back',
              data: {
                id: 'back'
              }
            }
          ]
        }
      ]
    };
  }
}

Register the new Quick view

Navigate to src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts.

export const DETAILED_QUICK_VIEW_REGISTRY_ID: string = 'HelloWorld_DETAILED_QUICK_VIEW';
  public onInit(): Promise<void> {
    // ...
    this.quickViewNavigator.register(QUICK_VIEW_REGISTRY_ID, () => new QuickView());
    this.quickViewNavigator.register(DETAILED_QUICK_VIEW_REGISTRY_ID, () => new DetailedView());
    // ...
  }

3 - ViewNavigator

this.cardNavigator and this.quickViewNavigator are instances of a ViewNavigator. The ViewNavigator's capabilities go beyond only registering new Views. The ViewNavigator is a state management API for the Card and Quick views. As Views are created, they are automatically pushed onto a View stack. ACEs can use the ViewNavigator to manipulate the stack.

  • ViewNavigator.push
    • Pushes a new View to the top of the View stack.
  • ViewNavigator.replace
    • Replaces the top View with a new View.
  • ViewNavigator.pop
    • If there is more than one View, pops the top View from the View stack.

3.1 - Navigate between Views

Navigate to src/adaptiveCardExtensions/helloWorld/quickView/QuickView.ts

Handle when an item is selected from the Quick view.

import { DETAILED_QUICK_VIEW_REGISTRY_ID } from '../HelloWorldAdaptiveCardExtension';
public onAction(action: IActionArguments): void {
  if (action.type === 'Submit') {
    const { id, newIndex } = action.data;
    if (id === 'selectAction') {
      this.quickViewNavigator.push(DETAILED_QUICK_VIEW_REGISTRY_ID, true);
      this.setState({ currentIndex: newIndex});
    }  
  }
}

Navigate to src/adaptiveCardExtensions/helloWorld/quickView/DetailedQuickView.ts

Handle when the Detailed Quick view's back button is clicked

public onAction(action: IActionArguments): void {
  if (action.type === 'Submit') {
    const { id } = action.data;
    if (id === 'back') {
      this.quickViewNavigator.pop();
    }  
  }
}

Reload the workbench, click on the Card to open the Quick view, and click on an item in the Quick view.

Try clicking "Back" and clicking on another item.

4 - onRenderTypeChanged

When an ACE transitions from one RenderType to another, onRenderTypeChanged will be invoked with the previous RenderType; this.renderType is updated at this point. This can be useful for any bookkeeping between the transition.

4.1 - Maintain the Card state when opening the Quick view

Navigate to src/adaptiveCardExtensions/helloWorld/HelloWorldAdaptiveCardExtension.ts.

Keep a private member to track the previous index during a RenderType change.

import { RenderType } from '@microsoft/sp-adaptive-card-extension-base';
import { DetailedView } from './quickView/DetailedQuickView';

private _cardIndex: number;
protected onRenderTypeChanged(oldRenderType: RenderType): void {
  if (oldRenderType === 'QuickView') {
    // Reset to the Card state when the Quick view was opened.
    this.setState({ currentIndex: this._cardIndex });
  } else {
    // The Quick view is opened, save the current index.
    this._cardIndex = this.state.currentIndex;
  }
}

Reload the workbench. Try opening and closing the Quick view after clicking on different items. Notice the Card View will remain in the state it was opened.

Conclusion

After this lab you should be familiar with:

  • Creating and registering Quick views
  • Using the ViewNavigator for navigation
  • Handling Actions from the Quick view
  • Using onRenderTypeChanged
  • Advanced Quick view manipulation

Clone this wiki locally