• David Tessaro

Custom Options for a Semi-Editable User Profile

Customize your User Profile widget to selectively allow editing of the profile fields, and to include a catalog link at the bottom.

Things you will learn in this tutorial:

  1. Clone a widget

  2. Create custom options

  3. Modify HTML template with custom options

The new user profile in Service Portal looks great. Add in the editable fields and it is downright slick. But what if your user profiles get updated by LDAP or something? You don’t want Johnny in Accounting to spend six hours writing his bio and taking the perfect selfie just to have it overwritten in the nightly sync.

Unfortunately, it’s an either-or situation. Either you expose the profile and let users edit the details, or you take it away completely. But what if you could allow just some of the fields to be edited? Now wouldn’t that redefine slick?

Let’s do it! We’re going to customize the User Profile widget so that you can decide which fields are editable for your users.

1. Clone the User Profile Widget

First, we need to make a copy of the User Profile widget. If you’ve never done this before, find User Profile in the Widgets list and open it.

Next, click the Clone button. This creates a new copy of the User Profile widget for you to play with. You’ll want to change the name of it. I’m naming mine “User Profile w Edit Options”. Click Update to save this new widget.

2. Create Widget Options

Now we’re going to create some options for the widget. We want to toggle the ability to edit each field in the HTML template, so we’ll need an option for each field. There are two ways to create a widget option. One is from the widget editor, and the other is doing it by hand right in the Option Schema field right here on the widget record. We’ll do the latter.

The syntax for a widget option is simple. It looks like a JSON object and follows this basic format:

[{"name":"my_option","label":"My Option","type":"option_type"}]

Our first option will be for the user’s photo, and we’re going to use a simple boolean type:

[{"name":"edit_photo","label":"Edit Photo","type":"boolean"}]

Next, let’s add options for all the other fields on the profile form. Note that we’ll be lumping the email and phone numbers into one property. Also note that there will be only one set of square brackets, which we’ll keep on the outside of our options. (Also also note that there’s no comma after the last option)

[{"name":"edit_photo","label":"Edit Photo","type":"boolean"}, {"name":"edit_title","label":"Edit Title","type":"boolean"}, {"name":"edit_company","label":"Edit Company","type":"boolean"}, {"name":"edit_department","label":"Edit Department","type":"boolean"}, {"name":"edit_location","label":"Edit Location","type":"boolean"}, {"name":"edit_bio","label":"Edit Bio","type":"boolean"}, {"name":"edit_contact_info","label":"Edit Email","type":"boolean"}]

Now take all this and paste it into the Option Schema field on the widget record. Then click Update to save your work.

3. Modify the HTML Template

Adding these options is not enough. Now we need to build them into our template. To do this, we are going to update the editable-by-user attribute of each of the fields in the HTML. You’ll find the first occurrence of this on line 29, which is for the title field:

<sp-editable-field ng-if="::displayField('sys_user', 'title', true)" editable-by-user="data.isLoggedInUsersProfile" table="sys_user" table-id="data.sysUserID" field-model="data.sysUserModel.title" on-change="titleOnChange" on-submit="titleOnSubmit"></sp-editable-field>

Look for the attribute/value editable-by-user=”data.isLoggedInUsersProfile”. The editable-by-user attribute controls the ability to edit the field. The value data.isLoggedInUsersProfile is a function that evaluates whether the profile being viewed belongs to the current user. We are going to extend this evaluation to test whether the Edit Title property has been checked in the widget instance.

To do this we will simply add in && options.edit_title == ‘true’ to the end of data.isLoggedInUsersProfile. So, line 29 now looks like this:

<sp-editable-field ng-if="::displayField('sys_user', 'title', true)" editable-by-user="data.isLoggedInUsersProfile && options.edit_title == 'true'" table="sys_user" table-id="data.sysUserID" field-model="data.sysUserModel.title" on-change="titleOnChange" on-submit="titleOnSubmit"></sp-editable-field>

We are going to add our options evaluations in eight more places, in the same we did just now with !options.edit_title. Here’s a cheat sheet for you:

  1. Company field on line 32: options.edit_company == ‘true’

  2. Department field on line 34: options.edit_department == ‘true’

  3. Location field on line 35: options.edit_location == ‘true’

  4. Bio field on line 36: options.edit_bio == ‘true’

  5. Contact info field group on line 54: options.edit_contact_info == ‘true’

Did you notice that we haven’t done anything with options.edit_photo yet? That’s because we need to treat that one differently. It’s not using the editable-by-user attribute. The HTML element we’re after here is a button. It’s on line 20:

<button ng-click="uploadNewProfilePicture($event)" ng-keypress="uploadNewProfilePicture($event)" type="button" class="btn btn-default send-message"> ${Upload Picture} </button>

We can pair the Angular directive ng-disabled with the expression options.edit_photo != ‘true’ to disable this button. Stick ng-disabled=”options.edit_photo != ‘true’” right between button and ng-click, so you have:

<button ng-disabled="options.edit_photo != 'true'" ng-click="uploadNewProfilePicture($event)" ng-keypress="uploadNewProfilePicture($event)" type="button" class="btn btn-default send-message"> ${Upload Picture} </button>

That’s it for the widget code. Click the Update button and let’s move on.

4. Place the Widget on Your Page

Next, we need to add an instance of this new widget to our User Profile page. Open the page by finding it in the Pages list, then use the Edit in Page Designer link to open the page in design mode.

You’ll see an instance of the original User Profile widget on the page You can delete this by clicking the trash can icon in the upper right of the widget instance. You’ll be asked to confirm the deletion. Remember, you’re only deleting this instance of the widget, not the widget itself, so it’s okay to delete it.

Now find your new widget in the widget list, and drag it onto the page where the previous widget was placed. It’s going to look exactly the same as the out-of-box widget:

Now when you use the pencil icon in the upper right you will see the new options we added:

5. Test It Out

Before we go toggling options, let’s get a baseline by visiting our portal page as it is. We should expect to see all our fields in a read-only state.

Now let’s go back to our widget options and check a few boxes. If you already closed that page, here’s an easy way to get back to it:

  1. Go to the Pages module.

  2. Either sort the list by Updated, or

  3. Search for the page User Profile (or whatever your page was called).

  4. Click the Open in Designer link.

Here we are back in the widget instance view. Click the pencil in the upper right corner of your new User Profile widget instance, then check all the boxes you want and click Save.

Now go back to the User Profile page in the portal and check it out.

As we expected to see, all the fields I checked may now be edited.

Now let’s add an option for selecting a catalog item to display as a button beneath the profile form.

6. Open Your Widget in the Widget Editor

Find and click on the Service Portal Configuration module in the navigator. Then click on the Widget Editor box:

Find your widget in the list on the left, or search for it by name:

This opens up the full widget editor panel, which may be scary for some. Don’t be intimidated, just click the menu in the upper right, then click on Edit option schema.

Now you’re looking at the Options Schema panel. Add a new reference option like I did here with the last item in the list. Click Save when you’re done.

Great, now we have a new option ready to use.

7. Update the HTML Template to Include the Button

Clicking Save in the last step will drop you onto the Widget Edit panel. Look in the HTML Template code for line 60 and put an empty line after it.

You can use this HTML snippet for the button:

Secondly, we are using the standard catalog item link href template with the value of our option to create a URL string for our link.

Plop this snippet onto that empty line 60, then click Save in the upper right.

Now we can configure that option to be whatever catalog item we like. Use Step 5 to get back to the widget options configuration panel and then choose a catalog item and click Save.

Finally, go visit the page in the portal as an end user would. Check out that spiffy button, and give it a click to confirm it’s working as desired.

And there you have it. Your user profile page is much more than it used to be. Let’s take a review of the steps we went through to lock down the fields on the User Profile:

  1. Created a copy of the User Profile widget.

  2. Added options for the fields on the user profile.

  3. Modified the HTML template to evaluate our options.

  4. Swapped the original User Profile widget for our new modified one.

  5. Verified that all the fields were read-only without any options selected.

  6. Selected the widget options.

  7. Confirmed that indeed the options resulted in editable fields.

  8. Added a new widget option referencing the Catalog Item table.

  9. Added HTML for a conditional button into our HTML template.

  10. Configured the widget option by selecting a catalog item.

  11. Tested the button.

Now you have the skills to go create options for any widget, and reference them in the HTML template (or the client controller script) to control the user experience.