Introduction
So, why did I write this post? The Portal Web API is awesome and it’s fast. You can empower users to create records, upload files, provide feedback in record time with very little friction. However, it works behind the scenes which can leave the user asking Did that actually do anything? Was it successful? Is it still doing it? Am I safe to navigate away from the page now?
I came across this on my Spotify clone project and again with my editable grid project and thought I’d share with you awesome people.
Providing visual feedback isn’t much additional effort. It’ll answer all the above questions and tends to give the impression that the whole thing is even faster than it is (although no actual difference!)
Visual examples
Here’s how that looks for my like button:
Here’s how that looks for my profile image upload
Here’s how that looks for a row in my editable grid
Note – I’ve also added some CSS to highlight which of the fields are ‘dirty’ as a way of reminding the user to save their changes
We’ll do this in 2 stages:
- Once when the Portal Web API operation begins
- Again, once the operation has completed
This is actually really simple to do. A single line of jQuery should do the trick (well, a single line for the ‘in progress’ message, and another single line for the ‘succeeded’ message). Here’s what we need to:
- Select the element we wish to update
-
Either
- Provide some text or HTML to override that element’s content with OR
- Add an additional HTML element to the page
Selecting elements
Note – if you’re already comfortable with jQuery selectors, skip ahead to the next heading 🙂
We’ll usually select an element using an id or a class. Here are examples of each:
Select an element e.g. an anchor tag (link) by id:
$(‘#submitPhoto’);
Select all elements e.g. anchor tags (links) by class:
$(“.like-button”);
Bonus: select a table cell <td> by data attribute:
$(‘td[data-attribute=”change-status”]’);
So what do we do with those elements now we can select them?…
Provide visual feedback by interactively amending the HTML of those elements
My usual approach for providing visual feedback is to use jQuery’s .html() to change the content of a HTML element e.g. the label on a button. It’s simply a matter of providing the HTML in quotes, like so:
$(“.like-button”).html(‘Saving…’);
Another approach for providing the visual feedback is to append additional HTML to the page using jQuery’s append(). You can see an example of that in the profile photo upload above. As well as changing the text on the upload button for In Progress, I use the append function to add the uploaded photo to the page. This one’s a little more complicated as you need to know some HTML but I think the result is well worth it.
$(‘div#showOnSuccess’).append(‘<img class=”img-responsive” src=”data:image/jpeg;base64,’ + profilePhotoContents + ‘” />’);
Where to place the jQuery to provide visual feedback for your Portal Web API operation
Seems simple enough, right? Now it’s just a matter of where that jQuery goes.
For the ‘In Progress’ message, I place the jQuery just above the Portal Web API request. If you’re not sure what this is, just look for the line starting with
webapi.safeAjax
Here’s an example of that (Don’t worry, I’ll share the full web templates at the end)…
function createLike(itemGUID,itemName) {
var dataObject={
“musdyn_name”:“{{ user.firstname }} liked ” + itemName,
“musdyn_ListenerGeneratedPlaylist@odata.bind”:“/musdyn_playlists(“ + itemGUID + “)”,
“musdyn_Customer@odata.bind”:“/contacts({{ user.id }})“
};
$(“.like-button”).html(‘Saving…’);
webapi.safeAjax({
type: “POST”,
url: “/_api/musdyn_likes”,
For the ‘Succeeded’ message, the jQuery should go withing the success function which is towards the end of that webapi.safeAjax function
Here’s an example of that:
webapi.safeAjax({
type: “POST”,
url: “/_api/musdyn_likes”,
contentType:“application/json”,
data: JSON.stringify(dataObject),
success: function(res, status, xhr) {
$(“.like-button”).html(‘<span class=”glyphicon glyphicon-ok” aria-hidden=”true”></span>’);
}
});
Code examples
Here’s the HTML and jQuery for each of the visual examples provided in the introduction…
Like button
Original HTML |
|
||||
jQuery to provide ‘In Progress‘ visual feedback |
$(“.like-button”).html(‘Saving…’); |
||||
jQuery to provide ‘Succeeded‘ visual feedback |
$(“.like-button”).html(‘<span class=”glyphicon glyphicon-ok” aria-hidden=”true”></span>’); |
Image upload
Note – I’ve taken a slightly different approach for the visual feedback on success. Instead of changing an existing element’s HTML, I’m appending a new <img> element to an existing <div>
Original HTML |
<a |
jQuery to provide ‘In Progress‘ visual feedback |
$(‘#submitPhoto’).html(‘Uploading…’); |
jQuery to provide ‘Succeeded‘ visual feedback |
$(‘div#showOnSuccess’).append(‘<img class=”img-responsive” src=”data:image/jpeg;base64,’ + profilePhotoContents + ‘” />’); |
Editable grid
I’ve used these same methods but I’m providing visual feedback for the record as a whole. Because I’m saving multiple records at once, the selector is a little more complicated. I don’t have a unique class or id to rely on so I’m using a combination of jQuery looping, $this and a data attribute to identify the required column to place the tick in (you can read more about this in my editable grid tutorial)… however the key point is that the visual feedback is provided in exactly the same way.
Original HTML |
<a |
jQuery to provide ‘In Progress‘ visual feedback |
$(this).find(‘td[data-attribute=”change-status”]’).html(‘Processing…’); |
jQuery to provide ‘Succeeded‘ visual feedback |
$(‘tr[data-id=”‘ + updatedRecordGUID + ‘”]’).find(‘td[data-attribute=”change-status”]’).html(‘<span class=”glyphicon glyphicon-ok” style=”color: #1ed760;” aria-hidden=”true”></span>’); $(‘tr[data-id=”‘ + updatedRecordGUID + ‘”]’).find(‘.dirty’).removeClass(‘dirty’); |
The above examples are all quite different in appearance but all using a very similar approach and usually a single line of code to provide the feedback
I hope you’ve found that useful and I’d be most excited to see you take these ideas to the next level and build something awesome!