SharePoint

Applies to: SharePoint 2013+

A while back I wrote an AngularJS app running in SharePoint 2013 and using lists as the backing store for some components. Without getting into the reasons this particular architecture was chosen, let’s look at an issue that came up.

The client asked us to show the popular items. There is a standard web part for this, but you can also query the search API directly by sorting by ViewsLifeTime:descending which is what we did so that we could display it in a custom Angular directive. No problem! Right?

It wasn’t until some time later that the client asked about the results we were displaying. The most “popular” items appeared to be the ones they had had trouble with behind the scenes and didn’t match their expectations about what users would be viewing.

When you view a list item (dispform.aspx?id=X) this view is tracked in SharePoint’s Usage Analytics (assuming you’ve configured this correctly). It’s this information that is used by search to determine an item’s popularity.

Unfortunately, it turns out pulling items from the REST API triggers no such view event. This seems obvious in retrospect, but until we really thought about it, usage tracking is just one of those magical behind the scenes things SharePoint does and we just assumed it would work.

This explains the results the client was seeing. The items they were having trouble with are the ones they were viewing directly (outside of the Angular app). While this wasn’t a ton of traffic, it was far more than any other list item was getting since they were only being viewed via the REST API inside a custom application. Ugh.

Fortunately, the fix for this isn’t too complicated, it’s just not very obvious.

Spoofing Item Views in JavaScript

You can log a View event using the SP.Analytics.AnalyticsUsageEntry.logAnalyticsEvent2 method. I had trouble finding any helpful documentation on this method or what the parameters should be. Fortunately, after some experimentation (and patience as the entries are not immediately available), I got it working.

Here’s the basic JS code which you can then adapt and make smarter:

For instance, I adapted the above into an AngularJS service and wrapped the call to get the site Id and user into a promise so that I only had to pull that once in my app, but all of that is up to you.

One nice thing about doing this manually is you can control when it fires. For instance, you might want to only log usage during reads but not during edits or exclude administrative accounts, etc.

That’s it! Now your custom interface can participate in the internal popularity contest!

Applies To: Office 365

Update

This solution is now officially a part of SharePoint PnP! Please use this repo for all updates, issues, contributions, and more. Whoo Whoo!

Modern listviews support the addition of custom formatting for most field types. This is an awesome feature designed to make custom formatting simpler and less administratively difficult than packaged solutions.

Unfortunately, the tooling is still very minimal. Users are given a simple text field within a panel to paste the JSON code and a preview and save button. The panel is clearly not designed to enable editing meaning that not only do users have to write code, they have to find someplace to do it.

The official suggestion is to use VS Code which will provide some auto completion using the standard schema. However, there are several downsides to this approach:

Requires a desktop client to be installed

Non developers that may have hung on past the initial mention of JSON are mostly gone by now

I previously released a verbose schema which makes editing in VS Code a lot easier, but still doesn’t solve the preview problems, learning curve, or the need to use a tool outside of O365.

Column Formatter

Column Formatter is a SharePoint Framework client-side webpart I’ve created using React and Redux. It’s designed to give the full power of VS Code editing while providing easy to use templates and wizards all within the browser! The goal is to make writing and applying Column Formatting easier and quicker for both developers and end users.

Development Details

I originally set out to make an Application Customizer SPFx extension that would sit directly on the modern listview page. Unfortunately, there aren’t APIs available (at least that I could find) to load the CustomFormatter library on the page if none of the columns are using it yet, nor a way to trigger applying the formatting to the listview without actually changing the field’s CustomFormat value.

So I’ve extracted the CustomFormatter library into my project and am faking it by providing it only the dependencies it actually needs. While this gives me full control to enable “as you type” live preview of rendering, it also means that things could get out of sync with O365 development. For now, I’ll do my best to keep things updated but ultimately I’d like to be able to load the office CustomFormatter module on demand.

Similarly, I had to extract the styles of the modern listview and the unique classes for CustomFormatter.

The editor is a custom build of the Monaco Editor(the editor that powers VS Code). Getting this built as a module that worked in SPFx was a real challenge, but worth it because of the immense power it adds.

This was my first experience with Redux. It was hard to wrap my head around at first and there is a significant amount of boilerplate code required (largely to play nice with Typescript), but I wouldn’t do any React webpart of even minor complexity without it! It simplifies state management and makes additional iterations of features much easier.

What’s next

There are a few templates and wizards included currently, but there are way more that could be added. I plan to keep adding these and am open to both pull requests and suggestions.

Wizards make it easy to generate Column Formatting without writing any codeTemplates provide you with starter code and sample data

I have submitted this webpart as an entry in the Hack Productivity 3 hackathon(Go vote for it, please!) which is why it’s currently hosted on my github. I’d like to get it included in SharePoint PnP if they’re open to it, although I’m not sure where it should go just yet.

More Information

You can find a lot more details about features and how to use Column Formatter in the ReadMe in the repo. I also created a demonstration video that covers a lot of the features:

Recently a new serveConfigurations section was added to the serve.json config file in new SPFx Extension projects. These are a huge help when it comes to debugging extensions and are especially helpful when testing ClientSideProperties.

Background

Prior to the introduction of serveConfigurations, you couldn’t just run the gulp serve command like you do for webparts since that launches the local workbench where extensions couldn’t (and still can’t) be tested.

So the advice was to use gulp serve –nobrowser and then just navigate manually to a page in O365 and paste an ugly (and easy to screw up) set of querystrings.

Waldek Mastykarz even created a gulp task, gulp serve-info, that made this a little easier. I used it in my extensions and it was a huge leg up, but the whole thing was still clunky and a significant complexity preventing new developers from getting into extension development (or at least frustrating them).

What was needed was something as simple as gulp serve that took into account your custom locations and unique property settings. Fortunately, that’s where serveConfigurations comes in!

Setting up your serveConfigurations

When you generate a new SPFx Extension you’ll find a couple of initial serveConfiguration entries were created for you automatically in the config/serve.json file:

The values of these configurations should remind you of all of those querystring parameters because that’s exactly how these are going to be used. These values will build the URL for you when you serve your solution. The IDs and properties all match what was generated (although you are unlikely to keep the testMessage property for long).

The first thing you should do is replace the pageUrl property with the page address in your O365 tenant where you want to test the extension. Keep in mind these values are NOT used in the final package and are only for testing.

The sample above is for an Application Customizer (which is why the location property exists). Each type of extension will have slightly different properties (same as the debug querystrings), but will be added for you with your extension.

Multiple serveConfigurations

If you’re only doing a single extension in your solution and you aren’t using ClientSideProperties then all you need is the default entry using your own pageUrl value. If however, you have multiple extensions, then you’ll want an entry for each so that you can selectively decide which one you are serving when running gulp serve.

It is also comes in handy when you want to test different ClientSideProperty configurations. For my Field Customizer sample SPFx Item Order I allowed users to specify an OrderField property. When it was present the extension did one thing and when it wasn’t it did another.

Using the serveConfigurations

Text in a json file! WOW! But how does this help?

Now when you run gulp serve the default serveConfiguration entry will be used and the browser will go to the pageUrl you specified and the debug querystring will be built using the values you provided!

Even better, you can specify which serveConfiguration you want to use using the –config parameter. So for the Item Order Field Customizer shown above, I could test the custom field configuration by entering this at a command prompt:

gulp serve --config=customField

Now the browser will be launched and my custom property will be set!

You can even see the URL that the browser will be sent to directly in the command output:

Aren’t you glad you didn’t have to type that (and get it right)? So, if you’re doing SPFx Extension development, serveConfigurations makes your life much easier!

Bill Baer will be delivering the keynote: SharePoint, OneDrive, and Digital Transformation – and there are a ton of other great speakers(plus it’s free)!

Our session is at 10:40 and will introduce you to the SharePoint Framework (both web parts and extensions). We’ll actually walk you through getting the various tools installed and ready (bring your laptop) so that by the time you leave you’ll know not only what the SharePoint Framework is, what it can do, and when to use it – you’ll be ready to start experimenting immediately!

I will be presenting 10 Ways SharePoint Online Will Benefit Your Intranet on Saturday, September 16th, 2017 in Kansas City as part of SPS Kansas City!

There are 20 different sessions across 5 tracks presented by some great speakers and MVPs. All of that for the low low price of free!

My session:

While many companies have already initiated transformation around their products and customers, that same level of transformation is often not happening around employees. Yet increasing employee productivity can come with an enormous ROI, by streamlining collaboration, reducing the amount of time employees search for content, eliminating manual tasks, and creating faster decision-making that leads to more agile employees and companies.

Discover how you can build a Digital Workspace for your employees by utilizing Office 365 and SharePoint Online to take your Intranet to the next level. By moving to the cloud, we’ll cover how your organization can start delivering more value at an even lower cost. Whether you’re considering a full migration to SharePoint Online or looking at a hybrid scenario, this session will help you envision an even more powerful Intranet for your company.

Key Takeaways:

Keep your team connected

Access your Intranet from any location and any device, with the ability to also include external parties. Keep information at the fingertips of your employees

Embrace an Agile Environment

Capitalize on regularly scheduled enhancements to the platform, as well as powerful development capabilities, such as the SharePoint Framework, Microsoft Graph API, PowerApps, and Flow

Safe and Secure

Discover how SharePoint Online meets security and compliance requirements in even the most demanding environments, while also providing a high level of reliability

Like this:

Applies To: SharePoint Framework

I had the honor of taking part in the PnP JS SIG call(Patterns and Practices JavaScript Special Interest Group) earlier today. On the call I was able to demo a sample I contributed for the SharePoint Framework Extensions called jQuery-Application-Toastr.

You can find a great write-up of the call on the Tech Community. You can also just watch the video directly on YouTube. You can even watch it right here, conveniently queued up to my demo, wowee!

Applies To: SharePoint 2013+

By default, when you click on a different page using SharePoint’s Search Results web part’s paging links (shown underneath the search results) the next page of results is shown but you remain at the bottom of the page. This is super dumb.

This is really easy to fix and requires no custom code at all! There is a property (not exposed in the UI for some reason) called ScrollToTopOnRedraw that is False by default.

To apply this setting to your Search Results web part, simply export the web part. You can do this by choosing to Edit the page and choosing Export… in the web part dropdown menu:

Now, open the .webpart file in a text editor like Notepad and do a quick find for ScrollToTopOnRedraw. Then change the value from False to True and save the file:

Now, choose Delete in that same web part dropdown menu on the current Search Results web part. Then click the Add a Web Part button. Choose Upload a Web Part under the list of categories, then click Choose File and pick the .webpart file we saved a minute ago. Finally click the Upload button:

You’ll probably be asked if you want to leave the site. It’s safe to choose Leave.

Click the Add a Web Part button again. Choose the Imported Web Parts category and find your newly uploaded Search Results web part and click Add. You’ll likely have to update the Refinement Target for any refinement web parts on the page as well.

Now, when you page results you’ll be taken back to the top of the results each time!