Friday 30 September 2016

Slide deck – Modern sites and the SharePoint Framework

Just a quick post of the slide deck I used for my talk last night at the SharePoint User Group. I talked about the changes for “modern sites” in SharePoint, and looked at things from the end-user and developer point of view (with respect to the SharePoint Framework). The link to the full deck is below.

I used this slide to speculate why I think Microsoft are motivated to change things like the “create or edit page” experience in SharePoint Smile

The Mum test

What I’m getting at is that many end-users (especially those who only use SharePoint occasionally) struggle with the current experience - using the ribbon, adding and configuring web parts and so on. Things are just too damn hard for SharePoint newbies.

And so we have a new set of web parts, and a new page editing experience. New web parts include the Highlighted Content web part, a PowerBI web part, a Yammer Embed web part, Office 365 video, and simplified text/image editors.

image 

image image

 

Slide deck

Wednesday 21 September 2016

Web part properties – dynamically populate Dropdown options in SPFx

UPDATED FOR SPFx RC0 – JAN 2017

When building web parts in the SharePoint Framework (SPFx), there’s often a need to implement custom web part properties – this allows the user to configure your web part in the way they need. Microsoft provide a set of core controls to use for this, one of which is the dropdown control (PropertyPaneDropdown). My previous article covered the basics of using the dropdown control (and others), but sometimes you need to go beyond providing a static ‘hard-coded’ set of options in the dropdown – in this post, we’ll show how to populate the control dynamically.

For reference, this article is part of the following series around web part properties:

Recap - populating the Dropdown control with static options

As a reminder, to provide a simple static list of options we use code like this in the getPropertyPaneConfiguration method:

PropertyPaneDropdown('dropdownProperty', {
                  label: 'This is the label',
                  options: [
                    { key: 'Red', text: 'Red' },
                    { key: 'Green', text: 'Green' },
                    { key: 'DarkBlue', text: 'Dark blue' }
                  ]
                })

But as we’re saying, having a static set of options often isn’t enough – we need to fetch them from somewhere when the user edits the web part. So let’s move on to that.

Dynamically populating the list – a simple example

Let’s start simple – in the code below, we change things so that the options are fetched from a separate method. I’m just showing the basics of using code to populate the list, but so far we’re not talking to SharePoint or another data source to get them:

So, we’re simply building an array of the appropriate object (IPropertyPaneDropdownOption) and returning it.

Dynamically populating the list – by fetching data from SharePoint

Things get a little more complicated when we need to talk to SharePoint, or make some other kind of async call to get the data. If we simply amend the previous code to call SharePoint (using spHttpClient or similar), we’ll find that we may have timing issues – our async method will fire, but getPropertyPaneConfiguration method continues to execute during this time, and the collection of items is empty. Some time later the collection will be populated, but it’s too late for our dropdown control.

The trick is to obtain the data, and then refresh the property pane by calling the onDispose() method of the web part. This patterns ensures that you are not delaying the load of the entire page or web part property pane, but that the UI is refreshed once the dynamic data has been fetched.
 
NOTE: in previous SPFx builds, the guidance was to use the OnInit() method of the web part – however, that led to problems in some scenarios, so that guidance has been updated to the pattern described here. For other things, OnInit() can be your friend though – just not necessarily for web part property pane work.

In this example we populate the dropdown with the SharePoint lists in the current site. We do this with an async REST call to SharePoint, which uses Promises in the code structure:

..and then in the getPropertyPaneConfiguration method, we kick-off the call to fetch the data at the beginning, and then in the control declaration we simply set the options property to our variable holding the array:

So that’s it – a web part property control using dynamic options!

Summary

The web part property model in SPFx is quite powerful, and is a great advantage of the SharePoint Framework compared to the classic “cloud-friendly web part” approach of using a Script Editor and some JavaScript. It’s possible to run code to build your web part property pane, but just be aware of timing and lifecycle issues. The onDispose method in a SPFx web part can be used to refresh the property pane once any additional code you have has executed.

Monday 19 September 2016

Speaking at SharePoint User Group UK – modern sites and the SharePoint Framework

SUGUKI’m looking forward to speaking next week at the UK user group (SUGUK), in my backyard here in London. It’s a time of pretty big change in the SharePoint world, and since the user group is typically a mixed audience I thought it would be useful to consider things from more than one angle – after all, the changes will affect a BIG cross-section of people and roles. I’m thinking mainly of the changes being rolled out to team sites and publishing sites this year, but of course these fit into a wider context of Office 365 Groups, PowerApps, and a whole list of things, so we should think about it in those terms. And of course, I will be covering some developer aspects and showing some SharePoint Framework code – and hopefully having some good discussion off the back of all this!

Here are the details:

The blurb

Here’s the title and summary for my talk:

Modern SharePoint sites and the SharePoint Framework
Microsoft have started releasing their big wave of changes to SharePoint sites in Office 365 ("modern" sites). This affects end-users in terms of user interface changes, but developers too with the introduction of the SharePoint Framework. In this session we'll consider both perspectives - we'll take a quick look at some of the changes in SharePoint Online team sites (including those which have not yet landed), including a look at "modern" page editing and the new set of web parts Microsoft are working on. We'll also consider how this affects on-premises SharePoint going forward.

From there we'll switch to a dev perspective - we'll build a web part in the SharePoint Framework, and start exercising our TypeScript, Gulp, and npm knowledge. It's a brave new world, but if you want your web parts to work in the new user experience you have to get on board!

Hope you can make it there if you’re local!

COB.

Tuesday 13 September 2016

Web part properties in the SharePoint Framework – part 1

Modern SharePoint pages have a new web part editing experience. This is powered by modern web parts and the new SharePoint Framework (SPFx), and developers who wish to work with these new pages need to understand the new model. As you start to build modern web parts, you’ll find the need to implement web part properties – so that your end-users can provide any options or settings required. Microsoft provide a set of common “property pane” controls such as textbox, dropdown, slider and so on – and it’s also possible to add an entirely custom control (something I’ll cover in a future article). In most cases the core controls are your starting point though, so in this article I’ll start looking at the TypeScript/JSON needed to use these controls.

First things first – reactive vs. non-reactive property panes

Perhaps the first thing to understand when implementing web part properties is that by default, the new page framework supports *immediate* changes to the rendering of your web part when a page editor changes a property. This is known as a “reactive” property pane - no more having to click “Save”, “OK”, “OK” just to see a change. Let’s take the example of a web part property specifying the description of the widget - if a user edits this in a textbox, and this is displayed in the main area of the web part, it will be dynamically updated as the user types. This happens automatically, although can require the developer to implement certain things in more complex cases.

Sometimes you want to disable this though – perhaps it’s not appropriate to have the UI constantly updating, or a lookup to SharePoint is needed each time there’s a change. You can disable the reactive behavior by adding this code to your web part class:

protected get disableReactivePropertyChanges(): boolean {
    return true;
  }

 

Structuring web part properties into pages and groups

Perhaps the second thing to mention is that the new web part property pane can be structured into multiple pages, each with groups of properties. And the best news is that we don’t have the baggage of the old web part properties on every single web part that no-one ever used (“Allow Minimize”, “Allow Close” etc.). So in the new world, a simple web part property pane with a couple of pages and groups might look something like the images below – take note of the page title, group title and paging controls:

SNAGHTML61509e7e

This allows us to better structure our properties, and so in my example the page 2 of the web part props might look like this:

SNAGHTML6152c7e6

You can continue to define additional pages and the framework will take care of providing paging in the UI for you. In terms of the code to do this (and define SPFx web part properties in general), all the action happens in the getPropertyPaneConfiguration() method. Here’s the code for the above (by the way, I’m using Gist for longer code samples like this one but have others “inline” in the post, so apologies that they look slightly different!) – anyway, we basically have two pages being defined in our structure now:

Using the different controls

So now we understand how to split our controls into pages and groups, let’s move on to the controls themselves. The first step in editing your web part code is to add import statements for TypeScript modules – we do this for each control we wish to use. So at the top of your web part class, move from something like this:

import {
  BaseClientSideWebPart,
  IPropertyPaneConfiguration,
  IWebPartContext,
  PropertyPaneTextField
} from '@microsoft/sp-webpart-base'

..to..

import {
  BaseClientSideWebPart,
  IPropertyPaneConfiguration,
  IWebPartContext,
  PropertyPaneTextField,
  PropertyPaneCheckbox,
  PropertyPaneChoiceGroup,
  PropertyPaneDropdown,
  PropertyPaneSlider,
  PropertyPaneButton,
  PropertyPaneToggle
} from '@microsoft/sp-webpart-base'

From there, we can start expanding the code in the getPropertyPaneConfiguration() method. We saw how to divide up our properties into pages and groups in the earlier code sample, but to zoom in on that for a second, here’s a specific change to move from the default arrangement to something with a second group. So we would move from the default of this:

groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                })
              ]
            }
         ]

..to..

groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                })
              ]
            },
            {
              groupName: "COB settings",
              groupFields: [
                PropertyPaneTextField('query', {
                  label: “Query” 
                })
              ]
            }
         ]

As with any JSON, you have to take care with closing brackets and braces! Note that for simplicity/illustration, you can see I’m not putting my strings such as the groupName and control label text into the separate strings class here – but in real life I recommend doing this to avoid magic strings littered through your code.

So, structuring your properties into pages and groups is pretty simple. Now let’s start looking at the individual controls – I’ll look at some here, and some in future articles.

Text box (PropertyPaneTextField)
Properties:

Property

Description

label Label shown next to the control.
description Description shown next to the control.
value Value in the field – can be used to set default text.
ariaLabel A non-visible label – used by accessibility-focused tools and browsers, as per the ARIA standards.
multiline Specifies whether the textbox is multiline (boolean).
placeholder Allows you to provide default placeholder text, shown when the control has no value.
resizable Specifies whether the control can be enlarged by the user (to make it easier to enter larger amounts of data).
underlined Whether or not the textfield is underlined.
errorMessage A static value for the error message – it’s not clear to me when you’d use this, because the error is always displayed. The onGetErrorMessage property is what you’d really use it seems..
onGetErrorMessage Pointer to function to use for validation – returns either a string (containing the error message) for simple cases OR a Promise<string> for more complex cases where you need to make an async call to SharePoint (or similar) to do the validation.

See below for more details.
deferredValidationTime Amount of time (milliseconds) to wait before showing the validation error message – e.g. to allow the user to finish entering a value.
The code:

Note that I’m also showing a simple textbox validation routine in the code below – note the onGetErrorMessage usage:

PropertyPaneTextField('textboxProperty', {
                  label: 'This is the label',
                  multiline: true,
                  resizable: true,
                  onGetErrorMessage: this.simpleTextBoxValidationMethod,
                  errorMessage: "This is the error message",
                  deferredValidationTime: 5000,
                  placeholder: "This is the placeholder text (shown when no value is entered)",
                  "description": "This is the description"
                })

private simpleTextBoxValidationMethod(value: string): string {
    if (value.length < 5) {
        return "Value must be more than 5 characters!";
    } else {
      return "";
    }
  }

What it looks like:

SNAGHTML4d5ddb9f

..and showing a more real-life example once the validation function has executed:

SNAGHTML4df82741

More advanced validation for the text box control

So in the example above, I showed a simple function to check the value the user entered was more than 5 characters. But what if you want to talk to SharePoint, or make some other async call to validate text box contents? In this case our function referenced in onGetErrorMessage must return a Promise<string> rather than a string – and things are a little more complex due to needing the right context for ‘this’ in your function. Here’s an example of an async textbox validation method – I’m checking if the value entered matches a list in the current site:

But there’s more. Initially I was getting errors indicating that ‘this’ was undefined in my function – manifesting in a ”Uncaught TypeError: Cannot read property 'context' of undefined” error as I was trying to access this.context in my web part code. So why was ‘this’ not populated? The answer is that it just isn’t with a default function pointer here. To get around this, we need to use the JavaScript/TypeScript ‘bind’ method. This allows a new invocation of the function where we can pass ‘this’ as a parameter – the receiving function then has the context. So where we reference our function in the onGetErrorMessage property of the textbox, instead of this:

onGetErrorMessage: this.asyncTextBoxValidationMethod,

..you need this:

onGetErrorMessage: this.asyncTextBoxValidationMethod.bind(this),

Big props to my colleague and friend Vardhaman for this – he has a great article on this specific subject (before the official docs mentioned it), and it’s there that I discovered this solution. Thanks Vard!

Checkbox (PropertyPaneCheckbox)
Properties:

Property

Description

text Text displayed next to the checkbox.
checked Specifies if the control is checked.
disabled Specifies if the control is disabled.
Code:
PropertyPaneCheckbox('checkboxProperty', {
                  text: 'This is the text', 
                  checked: true,
                  disabled: false 
                })
What it looks like:

SNAGHTML4e0dbd03

 

Dropdown (PropertyPaneDropdown)
Properties:

Property

Description

label Label displayed next to the control.
options An array of IPropertyPaneDropdownOption objects (similar to HTML <option> tag – defines the key/text etc. of the option). Can be specified in a static way, or fetched dynamically – see my other post (coming soon!) for details on this.
selectedKey Key name of the selected item. Can be used to set the initially-selected item.
disabled Specifies if the control is *disabled* (not sure why this is flipped the other way compared to other controls! Hopefully this will be made consistent in future releases..)
Code:
PropertyPaneDropdown('dropdownProperty', {
                  label: 'This is the label', 
                  disabled: false,
                  options: [
                    { key: 'Red', text: 'Red' },
                    { key: 'Green', text: 'Green' },
                    { key: 'DarkBlue', text: 'Dark blue' }
                  ]
                })
What it looks like:

SNAGHTML5c0d42aa

Summary

Building web parts in the SharePoint Framework brings a few new things, including a new model for web part properties. This is where the framework shines compared to other techniques like using a Script Editor web part and a separate JavaScript file – that method simply did not provide a way to use custom properties. In this post we looked at the first few of the controls, and also noted that populating a dropdown dynamically needs a specific approach which I detail in another article.

In future articles, I’ll look at other out-of-the-box web part property controls.