Creating a property pane for editing items in your SPFx web parts

It’s a great privilege and great fun to work with the exceptional team at Shire that’s building a bleeding edge intranet to support their now 24,000 employees and growing. The team is exploring some very new territory and learning a lot along the way. During last weeks webinar, Microsoft’s Mark Kashman promised we’d post some of the lessons learned in the project. It’s my pleasure to share with the greater world a tidbit of that knowledge in the form of how to create a property pane for an individual item, not just the web part using the SharePoint Framework (SPFx). Bob German has also done several blog posts on the lessons learned, you can start reading them at Bob German’s Vantage Point.

In the custom web parts that are being built the UX team had decided upon a configuration that includes both a basic and advanced mode. The advanced mode, is sourcing the items to be displayed in the web part from a list. I’m not going to talk about that here, what I’m going to address is the idea of configuring all the items in the web part itself by the addition of a property panel specifically designed to add or edit one of those items. This is a separate property panel from the web part property panel in which you would configure overreaching properties of the web part, such as layout or title.

I’ve created a simple example (lacking in everything but the necessary functionality) to illustrate this concept by creating a webpart that displays a set of links. It doesn’t really matter how I render those links, could be buttons, unordered list, etc… the point is that I would have an array of link items that would be curated through the property panel not an external list. SharePoint’s own modern hero web part does this, so it shouldn’t be that hard, right?! It took our team member Mike Tolly a good amount of reverse engineering to figure it out… and now his pain is our gain! Sorry Mike!!!

Within our web part we build a React component that has a set of properties. Those properties include things like linkItems which is the array of items I want to show, and functions for working on that array like editItem, deleteItem, and rearrangItems, etc…

Below is the code from this simple example where inside of the class definition for my web part I’ve added a property for the activeIndex of the item being edited, updated the render function to create my SpfxItemPropPane component, and created two separate property pane configurations in getWebPartPropertyPaneConfiguration and getItemPropertyPaneConfiguration. The real meat of the solution is in the protected getPropertyPaneConfiguration function where I make the decision to render the item property pane if the property pane is being called from code vs being called by the web part edit button. Obviously if you wanted even more item property panes you could add additional logic and properties to determine which property pane you were calling.

To complete the picture, my SpfxItemPropPane component tsx looks like this:

To get the complete solution, please visit my GitHub repo

Hopefully, even though this is a very simplified example, it will get you started if you’re looking to create multiple property panes in your SPFx web part. Happy Coding!

Utilizing ngOfficeUIFabric People Picker in SharePoint

One of the great joys of developing custom forms in SharePoint is developing the controls for some of the more complicated field types, specifically the Taxonomy Picker and the People Picker. If you’re sensing sarcasm, you would be correct. There are brave souls out there who recreated these components for us that utilize no less than five (and sometimes more) Microsoft Javascript libraries. The reality is, for the People Picker, which is what I’m going to be discussing today, you’re really looking for a type ahead input field that filters a list of people that you can retrieve from SharePoint. Sounds easy right… *sigh* if only.

If you’ve started using the new SharePoint Framework (SPFx) there is a big push to use the OfficeUIFabric. This framework provides not only styling but components that mimic what we’re given out of the box. Unfortunately, if you’re not a React framework user it seems that the investment by Microsoft is significantly lacking. I suppose this makes sense. Regardless, a team of non-Microsoft people embarked on a community project to create an AngularJS version of this library, ngOfficeUIFabric. Although it has some issues, overall it seems to work pretty well, but given it took me a bit to figure out what does and doesn’t work and exactly the best way to wire it up I thought I’d share my findings. This is where you can find the online demo for the people picker.

The idea, is to provide a function that either returns a list of people that match the query string (or not, there really is no requirement) or a promise to return a list of people. It supports Angular’s ng-model directive as well as ng-disabled. Obvious missing components are the ability to specify whether the field should be multiselect or not (it’s always multiselect), and the ability to trigger any functions on selection or selection change, I believe this is potentially a bug. Never fear dear reader, we can get around these limitations for the most part and the ability to avoid seventeen million additional libraries is a huge plus. Further, the architecture will certainly work in modern… so for all you brave SPFx coders out there you can take the same principles and apply them to the React component or even this Angular component depending on which framework (you want to use).

Ok, let’s get down to brass tacks…

Data Source

The people picker component wants an array of objects with the following attributes. We’ll call that object “Person”

Attribute Description
initials Used in lieu of a users picture with a background color.
primaryText The primary display text identifier of the user/group.
secondaryText Some secondary information you want to highlight about the user/group.
presence Text value, available options are available, busy, away, blocked, dnd, offline
group The results group you want to display the person in when the results of the search are displayed. This takes the form of an object with the following properties { name: “Results”, order: 0 }
color If there is no image, this will be the background color for the users “Initials” block. Available options are lightBlue, blue, darkBlue, teal, lightGreen, green, darkGreen, lightPink, pink, magenta, purple, black, orange, red, darkRed
icon This is the URL to a thumbnail image of the user, if provided this will be used in lieu of the initials and color attribute.
id Ideally this would be the id for the user in your site collection, but in lieu of that it’s a good option to use the users account name, or fully qualified domain name.

Now that we understand what structure the data needs to take, we need to go get it. To my mind there are two ways to solve this problem, the first, and probably the easiest would be to use Search. By which I mean the Search REST endpoint in SharePoint. That will be the direction I’ll take for this post, that said, you could always leverage my previous posts on utilizing the Microsoft Graph API inside SharePoint and use that to get the results. That would have the distinct advantage of being able to provide significantly more interesting information about the user if you needed it.. like manager assuming your user data is complete and up to date <insert plug for Hyperfish here>.

Note: NGFPP.currentSite is the url for the current site collection

Now, as you can see from a Search query I’m not going to be able to get the user’s id which would be needed to set the value of a person field. In this scenario, I’m specifically attempting to get all the available users from our directory, not only the ones that have actually logged into our SharePoint site. So, before I’ll be able to create/update an item in a list I’ll need to convert that person’s id (account name) into an actual id from the hidden users list in the Site Collection. For that we can use the ensureuser REST endpoint which is analogous to its CSOM cousin.

UI

Now that we have all the back-end pieces put together we can get started with the user interface. The one bug that I still haven’t completely solved is that of a wrapping issue, you can see it in the screenshot below. I suspect that the issue is related to various SharePoint css attributes and I just haven’t found the right one to override. But it’s trivial so I’ve decided to move on without solving it for now. Eventually I’m going to get it!

Since I’m on the topic let’s start with a couple minor CSS overrides you’ll want to include within your form. I’d strongly suggest scoping them to your form as well as you wouldn’t want to upset SharePoint styling elsewhere.

Now onto the HTML, here’s a small snippet of a table that I created for the “form”. I’m only showing the row for the People Picker in it. Of note, uif-people is linked to a variable on my controller that is assigned the function and the ng-model is linked to an empty array that can receive the selected “Person” items from the source array. In my example, I’ve decided to use the compact type and include a search delay… these are options and I’d encourage you to look over the demo’s to decide what’s right for you.

Controller

Single User Hack

One of the missing components of the solution is the ability to limit the user to selecting only one value. The work around I came up with, which I completely admit is a hack, was to implement a $watchCollection. This way when I see the model change I can determine if more than one item is selected and if so replace the originally selected item with the newly selected item. I’ve found in implementation this looks very smooth to the user so I’m happy with it as a work around. To add this to the above controller you would do the following:

Summary

So even with its flaws I’m moving forward with the implementation simply because it feels like a significantly cleaner solution. If someone out there takes this on and solves the css issues before I do PLEASE let me know and I’ll update the post with your solution. Hopefully I’ll figure it out soon!

Resources

The complete code is available on my GitHub repo if you’re interested in looking at the complete solution.

SharePoint time, is not your time, is not their time.

If you develop client side solutions for SharePoint you’ve either run into this or you will run into the following scenario. SharePoint stores all its date/time fields in UTC time. The site collections, sites, and the users, can have their own time zone settings. If you’re using SharePoint out of the box because all the content is rendered on the server and pushed to the client with all the date/time translation has been done for you. This makes wonderful sense, except when you try and write JavaScript against those same data points. The REST endpoints that return the data for you give you the date string in a format that is specific to the regional settings of the person asking for them. Sadly, this doesn’t translate as well to JavaScript as you might like. I’ve set up a scenario to illustrate the point with a couple of manipulations you can make depending on your desired goals.

Scenario

I have two PC’s (ok, one is virtual 😊). I set my virtual machine’s time zone to Pacific Daylight Time (PDT) and my main machine is set to Eastern Daylight Time (EDT). Then I have a SharePoint site collection whose regional settings are set for Eastern Time (or UTC-5:00 aka EDT). I created a list with a title field, and two date fields one to show date/time and one to show just date. The date only field was to illustrate that the problem exists regardless of whether the user intentionally sets the time or not. I created an item in the list from my computer set to Eastern time… Then I went to my computer set to Pacific time and created a second item. I set the dates and times for both items the same from their respective UIs. Again, this is to illustrate that the local time of the computer has no bearing on what SharePoint sees the date/time as. Regardless of whom entered the item the dates are displayed based on the regional settings effective on the site.

I’ve written some code that I’m going to expose using a CEWP… the code does the following things:

  1. Read the regional settings of the site.
  2. Gets all the items in my SPDateTime list and loops through them, for each item…
  3. Get the Items Date field, create a JavaScript date object, display the date object and the string that was used to create it.
  4. Get the Items Date No Time field, create a JavaScript date object, display the date object and the string that was used to create it.
  5. Adjust the Items Date field into the time zone of the regional settings in effect on the server and display it.
  6. Adjust the Items Date field into UTC time and display it.

Ok, so let’s start with the computer in EDT and take a look at what our client side code does:

What you’re probably noticing right away is that everything looks great. It’s just what you’d expect. So, what’s the problem… well… if you’re developing client side code and all the time zone settings for all of your users and their computers are going to be in the same time zone… absolutely no problem at all.

The tricky part begins when we look at the computer where the time zone of the computer is set to PDT.

Ok, so what happened here is that when the date strings were passed into JavaScripts Date() function, the browser is actually then converting that date into the local time of the computer. So 4/15/2017 12:00 am becomes 4/14/2017 9:00 pm (3 hours earlier). Again, this makes perfect sense, but if you want the user to experience dates independent of time zone, you’re in trouble. This can often happen if you’re building SharePoint “applications” date/times as fixed points in time that will be used as comparators.

Ok, so let’s look at a couple of workarounds and depending on your scenario you’ll have to decide if either of them work for you. I’m not going to go into how those regional/personal settings work but I will provide you a link to where Gregory Zelfond, gives a nice explanation: Setting proper SharePoint Time Zone for users.

Adjust date to time zone of “server”

The first manipulation I made was to adjust the date field to the time zone of the “server”, when I say server I mean whatever regional setting is in effect for that “page”. I personally can’t come up with a ton of scenarios where this is useful with the exception of making comparisons. In our PDT example which changes 4/15/2017 12:00 am to 4/15/2017 3:00am, which would be midnight PDT. I readily admit this is an odd scenario but you may need it (I actually have).

Adjust to UTC time zone

The second, which I think is entirely more useful, is converting to UTC time which basically means were going to ignore the time zone entirely. So, for our scenario this means 4/15/2017 12:00am shows up as 4/15/2017 12:00am.

The Code

For this solution, we’re going to need to make two REST calls the first will be to get the regional time zone of the web we’re working in. To do that you need to make a GET request to:

/_api/Web/RegionalSettings/TimeZone

The response for this call is the following, where we will use the Bias, and DaylightBias to calculate the region the server is operating in so we can mimic the values the server displays:

The second is to get all the items in our test list. Below is the code to generate the various date/time values I outlined above. Keep in mind, this is only a small code snippet from inside the loop that is traversing the items returned from out afore mentioned list.
*Assume that data is an array of responses

For the full code sample, you can go to my github repo and look in the SPDateTime folder.

For completeness sake, I should mention that if you’re going to be doing a lot of date/time manipulation it might make sense to utilize the moment.js library which makes a bunch of this stuff significantly simpler. I tend to be a minimalist when it comes to libraries, only using one when I have use for it. But if it makes you more efficient by all means don’t be a martyr and reinvent the wheel.

Hope this can help a few people out there struggling with date/times in SharePoint client side solutions.

Happy Coding.

JSLink Validation – from Basic to Advanced

Custom field validation using JSLink is an extremely powerful beast. In this post I’m going to make an effort to demystify the different levels of validation you can put into your custom template and how to put it together. Everything I’m about to cover has been covered before in different ways and in different combinations. My hope is that this will help separate out what’s needed and what’s not depending on your scenario… so to that end I’ll cover three scenarios. Basic, which will be OOB validation that is custom applied. By that I mean you want to optionally make a field required just like SharePoint does, but you want to control when it’s required.  Custom, which will be a custom validation function that renders its error message just like OOB validation error messages are rendered.  And finally, advanced, where not only do you want to write a custom validation but you want to control how the error state is communicated to the user.

So let’s start at the beginning and we’ll build on the solution from there. First I want to establish the framework for the solution:

Basic

Basic validation is fairly straight forward. You would simply add this code inside of your custom field rendering function (editTaskOwner).

First set up the form context and then create a new “ValidatorSet”:

In the next line we add the new validator to the validation set:

And then lastly, we attach the validation set to the field. In the case of this example I’m using formCtx.fieldName… but this could obviously also be a simple string. I bring this up, because there are limitations on what types of fields you can customize using Custom Templates, namely Taxonomy fields… this is a way to add validation to them from somewhere else in your code.

Note: If you’ve noticed I skipped line 4, more on that later.

The Result

Custom

If you want to write your own validation then you need to do a few extra steps.

Create the custom validation function. This function would go within your validation function but outside of the field custom render function (see the framework at the top)

Modify the RegisterValidator call

 (Optional) Depending on how you render the field you may have to add the following code. What I mean by that is if you use one of these OOB field rendering functions you do not need this line, if you develop your own layout then you will need this to “attach” the error message to the right object in the DOM. In this example my custom people picker field is rendering html wrapped with <div id=”TaskOwnerDiv”></div>. So I need to reference the div’s ID in the SPFormControl_AppendValidationErrorMessage call.

The Result

Advanced

So, if that didn’t seem advanced enough for you, the last scenario is that you may want to customize how the “error” is displayed to the user. Maybe you want to display an image, or collect all the validation messages into one area. That’s possible by doing the following:

Write custom error rendering code. This code needs to be completely outside of the custom rendering template code. Here’s a really basic example.

Modify the registration of the error callback, which causes your custom function to be fired if the isError flag is true.

The Result

So, as you can see custom form validation is extraordinarily powerful with Custom Templates and can allow you to really take SharePoint to the next level.

SharePoint 2013 JSLink – All Fields Rendered

While creating a custom Client Template using JSLink, I came up against the issue of knowing when all the fields were rendered on the form.  To explain where the issue arises let me first take just a moment to explain when building a custom template for this type of form, where you want to manipulate the fields, you have available to you both a Pre and Post Render function.  What that does is fire the function attached to it either pre or post each custom field rendering being executed.

The reason I bring this up is that there could be some misconception that it fires before field rendering starts and after all field rendering is complete, but that’s not the case. So if your form has 10 fields, these functions will each fire 10 times.  I also found document.ready to be unreliable as it often fired before all the fields were rendered, and further, if I needed to make decisions based on the context of the form, I would no longer have access to that information.

So, the solution does in the end involve the OnPostRender function of the Template Override, but what you do there is what counts. So just to put everything in context, and for brevity, here is the shell of the custom Client Template file.  Note the declaration of the postfields variable inside of My.CustomTemplate.

Ok, now we need to fill in the onPostRenderTemplate function.  Primarily, we need to know when we’ve gotten through all the fields on the form. This is accomplished by incrementing the "global" postfields variable within the onPostRenderTemplate function.  The question is what are we testing it against to know when we've rendered all the fields.

The answer is JavaScript prototype function keys which seems to be fairly well supported.

The Object.keys() method returns an array of a given object’s own enumerable properties, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).

Ergo, if you look at the ctx.Template.Fields and get the length that gives you the number of Fields on the form that will be "rendered" and provides you a way of telling when the last Field has been rendered.

So now I can execute some fancy functions to do thinks like:

Hide Fields

Modifying the Fields label to make it look like it was Required

or some other post rendering customization based as I stated on values in the ctx variable.