Using the OneDrive File Picker in SharePoint Framework Solutions

Lessons Learned from the #SPShire Project

This is the one of my lessons learned from the Shire Hub Intranet project, based on the forthcoming SharePoint Communication Sites.

The lessons in this blog series are:

  1. Previewing and Opening Office Documents from the SharePoint Framework
  2. Using the OneDrive File Picker in SharePoint Framework Solutions
    (this article)
  3. Creating Reusable React Components for SharePoint Framework Solutions

This project on github contains the sample solution for all three articles.

Using the OneDrive File Picker in SharePoint Framework Solutions

MikeTollyQuestionDuring the recent webinar explaining the Shire Hub project, Mark Kashman asked BlueMetal’s Mike Tolly how he developed the needed web parts. According to Tolly, it required “reverse engineering the Microsoft hero web part” to build web parts as rich and advanced as those from Microsoft. This article reveals one of the secrets Mike discovered: how to launch the OneDrive “file picker” to browse SharePoint content, so a user can navigate the libraries and choose a file.

The link picker swings out on an Office UI Fabric Panel component. If you haven’t checked out the Office UI Fabric React Components, you’ve been missing out! Stop right now and browse the catalog, where you can see the components in action and see how incredibly simple they are to use!

The link picker itself runs in an iFrame pointing to /layouts/15/onedrive.aspx with a bunch of query string arguments. Why an iFrame? Well it actually makes a lot of sense, given the amount of complexity in the link picker and the fact that you rarely use it. Why load all that stuff on every page, just on the off chance you need to browse for a document? Over time I’ve developed a love/hate relationship with iFrames, and this is one use I love.

In the sample solution, the code for dealing with the link picker is isolated in a React module called LinkPickerPanel.tsx. Here is the function that builds the URL for the iFrame.


private getDocPickerUrl(){
  const anchor = document.createElement('a');
  anchor.href = this.props.webAbsUrl;

  let typeFilter = '&view=2&p=2&typeFilters=';
  if (this.props.linkType & LinkType.folder) typeFilter += 'folder,';
  if (this.props.linkType & LinkType.doc) typeFilter += '.doc,.docx,.xls,.xlsx,.pot,.potx,.ppt,.pptx,.vsdx,.vsdm,.vsd,';
  if (this.props.linkType & LinkType.image) typeFilter += '.gif,.jpg,.jpeg,.bmp,.dib,.tif,.tiff,.ico,.png,.jxr,';
  if (this.props.linkType & LinkType.page) typeFilter += '.aspx,';
  typeFilter = typeFilter.slice (0,-1); // Trim trailing comma
  typeFilter += '&picker={"sn":false,"v":"files","id":"1","o":"';

 return anchor.href +
   "/_layouts/15/onedrive.aspx?id=" +
   anchor.pathname +
   typeFilter +
   anchor.hostname +
   '","s":"single"}';
}

The LinkPickerPanel has a property that filters the types of documents that can be picked. This is used to build the typeFilters query string parameter; OneDrive takes care of the rest.

The iFrame is rendered on the Panel component and is simple enough in itself.

<iframe src={this.getDocPickerUrl()}
  role="application"
  title={strings.LinkPickerSelectFromSiteTitle}/>

The link picker iFrame needs a way to communicate with our code when a user selects a document, or cancels out of the link picker. Here are the functions to add and remove the message listener and to handle incoming messages. The component adds the message listener when the panel opens, and removes it when it closes.

private addMessageListener(){
  addEventListener('message',this.onMessageReceived.bind(this), false);
}

private removeMessageListener (){
  removeEventListener('message',this.onMessageReceived.bind(this),false);
}

private onMessageReceived(event){
  if (event.data.indexOf('[OneDrive-FromPicker]',0)===0) {
    const json = JSON.parse(event.data.replace('[OneDrive-FromPicker]',''));
    const eventType = json.type;

    switch (eventType) {
      case 'success':
        const url = json.items[0].sharePoint.url;
        this.resolvePickLink(url);
        this.closeLinkPanel();
        break;
      case 'cancel':
        this.rejectPickLink();
        this.closeLinkPanel();
        break;
    }
  }
}

The messages come in with a heading “[OneDrive-FromPicker]”, followed by a JSON structure that indicates the event type and the link url chosen. There’s probably a lot more you can do with this, but there seems to be no documentation. (If there is documentation I’ve missed please let me know in the comments! I will thank you and update the article. This appears to be similar but not the same.)

The story continues in the next article, where I’ll discuss how this was wrapped into a reusable React component that’s shared by a whole suite of web parts.

2 thoughts on “Using the OneDrive File Picker in SharePoint Framework Solutions

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s