CSS for InfoPath forms – The best way to style InfoPath forms for Mobile

Infopath forms in SharePoint have some weird css styles when inspected.

There area number of ways to include css (see this link: Add-a-Custom-Style-Sheet-to-a-View.aspx) but they are limited by the weird, and what appears to be, computed class names.An example

This is really frustrating when trying to target specific elements, nobody wants to write css with that!!

I find embedded form web parts to be the best way to include Infopath forms in Sharepoint and they allow some external manipulation – such as query string integration and filtering – and also enable easier styling on the rendered objects via a script editor webpart.

Script Editor webpart

An interesting problem raised its head – making InfoPath forms ready for mobile & tablet and finger friendly – the multi choice selection boxes have very little in way of styling that you can access, just padding, font size, borders… The lines are too close together and the checkboxes are too small.

Sadly these boxes don’t have a nice targetable name, they are part of a fieldset in a stupidly named div, so we can’t easily specify what to manipulate and just chuck in some css. We also want to change all the checkboxes throughout the form not just one field.

We can however use attribute selectors in CSS = [attribute$=value]

See here for more info http://www.w3schools.com/css/css_attribute_selectors.asp

Simply add the following code to the script editor webpart and bingo… finger friendly InfoPath


<Style>
input[type="checkbox"]{
padding:5px;
height:25px;
width:25px;
}
</Style>

Office365 and InfoPath – GetUserProfileByName is not available – a solution

Whilst working on client project recently that involved InfoPath within Office365 I immediately wanted to use a commonly employed technique with previous projects – using the GetUserProfileByName web-service to obtain the users first and last name.

There are a number benefits to doing this, especially when the project inevitably involves workflow, custom library views, webparts etc to have a personalized experience for the user. For this specific project we needed to get the user of the form within the document as they were to form official standalone documents (as in out of the SharePoint document library context).

Unfortunately there is a BIG limitation…

“This issue occurs because loopback protection is enabled in the SharePoint Online environment. Loopback protection must be disabled for InfoPath forms to be able to connect to a SharePoint Online web service.

Any time that you make a call to the same server from an InfoPath form, the requests to loop back. This works only when loopback protection is disabled. For security reasons, loopback protection is always enabled in SharePoint Online. This is a known limitation of InfoPath forms in the Office 365 SharePoint Online environment, and there is no workaround for this issue.
Here is the article for your reference: http://support.microsoft.com/kb/2674193

So we need another way to get the user data from within Office 365 and into the InfoPath form and I devised the following solution:

The overview is as follows

  • an InfoPath webpart
  • a query string filter connected to the InfoPath webpart
  • a javascript file to add the query string parameter

Now I had to provision a page with the Infopath webpart and a few other connected webparts

I then needed to get the InfoPath form to react to a query string filter webpart

Passing Parameters to Infopath – By Tomasz Szulczewski

Next I added some JavaScript via a script editor webpart to read the current user name from the user profile service view CSOM

I used some of the script from Kit Menke’s blog here http://kitmenke.com/blog/2013/10/31/pass-user-information-from-sharepoint-2013-to-infopath-2013/

I simplified his script to just read the current user via “get_title()” and then pass this to the “window. location”

This redirects to a url with a query string parameter “CurrentUser” with this value

…aspx?CurrentUser=Username

making sure to redirect only if the string “CurrentUser” is missing from the url. See the “check” statement…


function CustomExecuteFunction() {
var self = this;
self.context = new SP.ClientContext.get_current();
self.web = context.get_web();
self.currentUser = web.get_currentUser();
context.load(self.currentUser);
self.asyncSuccess = function(sender, args) {
var user = this.currentUser;
console.log('asyncSuccess', user);
loc = window.location.href;
check = loc.indexOf('CurrentUser');
if(check <0)
{
// if not the redirect with appended query string
window.location= loc + "?CurrentUser=" + user.get_title();
}
};
self.asyncFailure = function(sender, args) {
alert('Request failed. \nError: ' + args.get_message() + '\nStackTrace: ' + args.get_stackTrace());
};
// actually fires off the AJAX request
// more info: http://msdn.microsoft.com/en-us/library/dn168907.aspx
context.executeQueryAsync(
Function.createDelegate(self,self.asyncSuccess),
Function.createDelegate(self,self.asyncSuccess)
);
}
ExecuteOrDelayUntilScriptLoaded(CustomExecuteFunction,'sp.js');

So I now had the current user in the url and the query string filter webpart reading the value and passing this to the InfoPath form field – I then had a people picker field read this value and bingo I could interact as if the original query was there.

Hope this helps someone else.

Thanks

Ryan