Skeleton Loading in Service Portal: Part 1 (Live)
[Music] you welcome to code creative I'm Travis Tolson hopefully this thing's going well and we're up I hope you will find out soon enough I suppose so today I'm going to take a look at skeleton loading in service portal so for those who are unaware skeleton loading is that fancy little thing in you see it in Facebook social media sites when it initially loads you know it'll pop up with kind of these placeholders I can be very useful when you're loading side content I wouldn't normally recommend this for the main content you know but in service portals if you're loading certain pages where you've got some you know sidebar widgets it can be useful to load those on the side that way your main content displays faster and you can turn around and load that additional data on the side after the main content has loaded so this is completely unscripted doing this ad hoc so we're gonna be exploring this one together so to go ahead get started I want to create a scoped application see this is a great part about this is that you get to see just how much I have no idea what I'm doing half the time hopefully my edits in the other videos makes it look like I know what I'm doing some of the time but most of the time I'm just kind of fumbling around hoping for the best alright there we go now we're getting somewhere so we'll call this one the skeleton loading widget actually you know what now I don't like that we'll just go it cook creative widgets that way if I do more of these in the future with service portal widgets maybe I can just reuse the same app we'll just continue in studios so I don't have to fill out the other end Phil ah and I'll leave this one open coz studio has some cool little launchers for some of the service portal stuff I've never really tried it from in here before widget service portal so will kind of give this a shot and see what happens okay so this launches the widget editor now normally I would go through the primary ListView and go through the main interface just because well honestly I don't adapt well to new things I've gotten used to using all the regular list views and such but we'll try something new today do the create a new widget simplest skeleton load and now we won't create a test page at least not yet we can create one later if we need it and they see a loading icon but I don't know what's actually happened here ah there we go alright so to start up here I'm gonna enable preview alright so now we should get a good preview over here and the first thing that I want to do code wise is just kind of start setting up a basic scaffold over here so class panel panel default and this is just using the bootstrap panel okay so I've got some lines there let's see I want to say it's panel heading and we'll save that bump up our preview okay we're slowly snapping some stuff together here all right so next up there's going to be basically two different views here ultimately what we're going to have is a the skeleton setup which is just going to be the basic placeholders and then once it's loaded then we're going to display the actual content so I think what we want let's see I'm gonna have to go back to some bootstrap 3 panel because I can't quite remember offhand how to put together these panels and I don't know how other people are with this I mean I imagine that there are some people that are just so daggone good that they don't even have to worry about silly things like documentation they can just flip it from the hip and run with it but for me not so much here we got list group this is what I'm looking for so this is this is what I want is those nice clean dividers going between you know and using the bootstrap code just help simplify some things so we're gonna add this scaffolding in here save it and that should give us basic setup to start with okay now as I said we do want two of these the first one is going to be our skeleton and the second one is going to be the actual data okay so I'm going to delete these off of here the second one is going to be my actual data I want to condition display these so I'm gonna create a scope variable here and we'll call it now that's that's actually bad let's call it is loading and we will default to true that way it's going to show the skeleton initially and then once loaded we'll update is loading to false and that will set us up with the actual data ng if C dot is loading if not C dot is loading and it's basically what we've got here is we've just set it up so that these two different you ELLs will show conditionally and depending on whether or not this flag is shown so if it's true you can see that I've got the five items from up top if it is false it should just show the one all right there we go this is actually working out better than I had hoped okay so now that we've got the two panels showing I'm gonna go ahead and leave this secondary one basically because what I want to do is set up our server-side code to pass some data back so I'm gonna put this in a function and we'll just call it now I'll call it get list items hardest thing in programming is naming things and cache invalidation wasn't I don't know vember it's something along those lines let's see so get list items this is where the glide record comes in and again I'm sure a smarter person than me would have this on a macro where they like click a couple buttons and it happens but no no I do it the long way every single time and I know some guys like Stephen Bell would shoot me for the gr and tell me to name it something better but I'm sticking to my guns I'm going with the function name so we'll query from incident and gr dot o let's do a set limit and we'll do 5 items and so later on we can go back and we can add instance options we can add you know we can make some more of this dynamic but by putting the hard code in I can quickly scaffold things up da Dada query let's just go with the actives for now actually let's go add in coded query because that's gonna make it easier to adapt it to instance options later hon and share dot query and watch our next now in our in our Glide record loop and ultimately I need and items array and I know that there are a number of service portal api's that will let you quickly generate an array of objects more often than not I don't end up using those a lot of times I'll end up creating my own custom objects and that's just because it allows me to clearly see from this server script without having to log it out to console you know I can come in here and I can quickly see exactly what the structure of this object is supposed to be and again I know different folks have different preferences when it comes to these sorts of things for me this is just how I like to do it so now normally at this point you know this object here is ultimately going to become our view model so you know a lot of folks will turn around and turn around and set this up so that it's the names that the property names reflect the underlying data model names I actually try to push myself to go in a different direction so for example let's say in fact let's go ahead and let's shift over here real quick I'm going to jump into my iPad here and Sketch up a couple things real quick so ultimately what I am hoping to accomplish is to have a panel and what I want to show is a let's say a title and then maybe a narrative box and then we'll show off to the side down in the corner here some metadata so let's go with that basic construct I'll flip back to the main screen so let's go with that basic concept so we'll have a title we'll have a short description and we'll have a meta list and for now i'll hard-code this list and we'll see how things get alright so for the title and let me go ahead and switch back to single quote just for consistency and because I usually end up using single quote anyway I don't even know why I did double quotes this time again this is the fun thing about going live is that all this stuff that usually gets edited out of my videos all of the oh wait I don't like this oh wait I don't like that oh wait what about this all that goes away and I can't protect myself anymore I just have to wing it alright so let's go with get the value I think this is how we do it one of the two gr there's the there's the element where you turn around and do like gr name dot get value and then there's this approach and I can't remember which one works in scoped applications I'm always having to go back and figure out which one it is I think it's this one that works so we're gonna get the number field and actually we'll go I am all over the place yeah title value value display value get display value all right I was starting to get somewhere here okay and then short description will do and then meta meta will need a couple things meta we're gonna need field name we're gonna need value and display value yes actually I can basically just paste yeah okay so for the meta let's go with let's go with assigned to I am explicitly avoiding a date/time field so that I don't have to deal with that right now maybe we can go back and add that later okay and Sharon I can't [Music] get label I think that's the one I want science it all right let's go with that and see how this goes so next up I need to return this out to a data phone or to a data object so we'll go with data items is equal to get list items and this is another thing that I like to do in my widgets is I like to separate out first I do like to separate out into functions makes it nice and easy to collapse second of all I like to put my inputs up top and my outputs down at the bottom I've seen a number of scripts where you know you get a bunch of data dots all strewn throughout and it's very challenging to see what the interface of your server script is what's coming in what's going out so I like to actually separate out the inputs at the top and the outputs at the bottom and use simple variables in the middle in order to encapsulate all of the different behaviors or just use functions to encapsulate the behaviors and use the returns which reminds me return items that would have been bad to miss that all right so save it nothing should happen no not great operation fun with scoped applications okay so next up let's do not there let's do it down here on the LI we're gonna do ng repeat iterate through our C dot data thoughts items and of course we need item in all right so that's gonna iterate for each item in C data items and you know for those who are a little bit newer to service portal data items in your server script gets passed into your client controller as cdata iOS well technically it's this dot data items which is angularjs --is controller as behaviors but since we're assigning see the value or the reference of this I think that's the right lingo since I'm assigning it the this reference I have C beta dot items over here okay so next up next up we need to get our display right so let's do a div and we're gonna show item dot title dot display value and then we'll show div to is going to be a short description and then the last div is gonna be our meta and this starts to show some of the advantages of using a a separate language for your view model from your roll date underlying data model because now at this point I can easily adapt this this glide record script to open it up a little bit more you know I could switch from incident table to request table I could switch from request to catalog item I could switch from catalog item to knowledge base and this widget would still work regardless so that allows me to more easily pull stuff out into into instance options into configuration data while still leveraging the same exact language in my view model and therefore in my HTML template over here so with that let's save and see what happens fingers crossed no something broke you got a question munchkin no my Otis was thinking of joining the live stream but he but he backed out um let's see what did I do wrong wait 400 bad request something about guided tours I don't know what happened there did it just take a lot of load cuz I got it now alright I guessed it I guess we're okay now I guess we're okay okay so let's try that again so you'll notice that there's no the skeleton portion never shows up it doesn't show up at all and that's because we are well first of all it's set to false so we're never actually loading so next up what I want to do is let's actually come in here and use uh-huh-huh let's go back to our Docs page developer there we go all right so I'm gonna check out the api's here I don't know if this one's in here I'm looking for this server dot update update state object on the server within a given scope this method is similar to server dot update but includes a dollar sign scope parameter no example that's okay alright so anybody want to place bets on whether or not Nathan Firth is the first one on the list let's say C dot server dot update then okay so that's kind of what we're looking for is this right here so the C dot server to update is going to allow us to from our client script wherever that land here we go from our client script it's going to allow us to and actually let's put this one in a function as well load list items all right so what we've got here is we're gonna do seed server dot update then ok so what's gonna happen is when we call C dot server dot update it's going to go back to the server and it's going to rerun our server script now there's two different variations of this function now that I think about it darn I was hoping it would autocomplete and give me some Intel one of these functions allows you to pass an input variable back the other if I remember correctly pass is the data object back to the input either way the difference between the initial run on the server script and AC dot server dot update or AC dot server dot get is that the initial run has input set to undefined any subsequent call is going to include an input variable of some kind I want to say that C dot server dot update passes the data object back and then so that's an asynchronous call so once the server finishes running the script and returning the data back it's going to pass that data back into the function that we provide to the venn call and you know for those interested in more you can look up promises Venables they go by a couple different names but basically it's just a way to pass a callback function in a cleaner way than the usual callback hell that you end up in so if I remember correctly I believe it passes back a response object and let's say [Music] let's just go now let's behave ourselves go with a console.log cuz I honestly don't remember alright oops and I forgot functions must be called and again putting everything in a function it provides for a much cleaner code I would much rather collapse all my functions and see the final logic down at the end I would rather have a setup that provides scaffolding followed by execution rather than try to read a bunch of spaghetti code so I try to put as much structure into my code as possible alright let's see what we get inspect element console here's our object oh well that's a pleasant surprise so I probably use I guess I use C dot server dot get more often because in fact it looks like it passes it back were uh you know what it's entirely possible it is entirely possible that C dot server dot update automatically assigns our C dot data to [Music] the response object now in in C dot server dot get you actually have to do you actually have to execute this function and do something with the data to assign it back but I am thinking that maybe with the C dot server date it automatically handles that binding which sounds familiar it's been a little while so we're actually going to cap that off there and we're going to experiment with something so going back to the input this is where I can turn around and specify if input do this so what this is going to do is it's going to take the loading data items it's gonna take loading data items and it's going to pull it out of the initial script run so now when it initially runs the script this function won't even be caught that allows you know this entire widget to skip the initial data load it skips the entire query and the performance hit associated with that query and just allows that widget to render the skeleton first of course that's assuming this is set to true and then the last bit here I'll actually add this back because we do need one last piece and that is once our C dot server dot update occurs we need to set C dot is loading to thoughts because we're no longer loading data let's see what happens close close close but no cigar if you paid attention to the preview over here watch again I'm gonna save and you're gonna see that quick blip of a skeleton that pops up let's see so let's go ahead and say C dot data is equal to data maybe I don't know if my coat broke or if it's still loading I don't know what happened at all Oh what am I missing what am I missing nothing apparently okay let's try that again with the seedot data let's see how this goes [Music] console data nothing input data items get list items all right so working theory if you remember what I said a moment ago one of these functions get or update passes the has to pass an input object I don't see it in here but possibly this is the one that has to pass an input so we're just gonna pass an empty object yeah so let's try this so one of the cool things in service portal and I forget who taught this to me but it blew my mind when I learned it you can actually put console dot log statements in your server script and it will pass that information to the client side and actually log those statements out so ya input nothing no input johnny-five would not be pleased um what am I missing hmmm alright let's see if we can find some other documentation I am looking for it I'm looking for it not using anything from input their data dot items what I'm gonna switch for a second to see dot server get because I'm not quite sure what I'm doing wrong I don't want to be overly hung up on this you yeah I am not sure what the issue I'm running into here is C dot server duck get new inputs then okay so if they jump back to my script here C dot data see that server to get data then see the data object I'm getting back here is still empty we're still not hitting the input and I don't know why let's see play send a test objects okay we've got input that time but not when I passed C dot data that's kind of wild so if you see when I'm using the C dot data as my input objects it's not hitting the if input I don't remember this being the case in previous versions I don't know if I'm doing something wrong or if maybe I've just never actually done it this way before but when I use a blank object it comes back just fine and I get my data coming back what about when I hit update does it do the same thing no updates still gives me trash yeah I'm really not a hundred percent sure what's going on with that what exactly I'm doing wrong I'll have to check it on some other versions and check it against some other code but to keep us moving along here what I want to do is you know keep us keep us moving I've managed to get the get it working with the get function so the get function is actually sending back a response object and we want to set C dot data to response dot data and so this should get us there negative data is not defined well that's unfortunate oh the danger of logging there we go okay now we're in business all right so let's go ahead and strip out the logging that was just for debug purposes we don't actually need it so we're gonna save it and what you're gonna see is you'll see this initial list load first very quickly and then you'll see the the this these incidents load after so we'll save it and boom and it's very very quick it's it's barely noticeable now the thing here is that when you're adding multiple lists each of these queries stacks on top of one another and the live pressure yeah thanks Josh no pressure at all [Laughter] so it's very it's very very quick with a single widget but if I jump over to you know some of our standard service portal pages and I'm gonna pull this URL and we'll jump over oops Espie Espie so if i pull up our baseline service portal you know some of these some of these widgets like my open incidents we could potentially load after the initial page has loaded you know this is especially the case when we move to top-rated like a knowledge article for example you know you notice that there's a bit of a load there we've got to load our knowledge article then we have to load our sidebar data you know by using some of the skeleton loading we can offload the unnecessary data load that the secondary date of the sidebars we can offload that after the primary data has already been loaded and rendered into the browser given the user a better experience overall and really speeding up those load times now this can also work if your main content is slow to load so instead of getting you know the little dot dot dot ellipsis up here you know they can get an initial hit showing uh here's you know something's happening something's loading you do want to test your user base with this though because I have seen a couple of studies out there with skeleton loading where it actually created a negative perception in some cases when loading the primary data as compared to you know how service portal works where it's got the dot dot dot and there's a number of running theories on why that's the case on why it the skeleton loading does really well in some cases and really poorly and others in terms of improving the perceived load time but it is one of those studies that has gone around and nobody's really pinpointed it down yet at least not to my satisfaction anyway I haven't been satisfied with the answers given yet and I think some study is still needed and of course you know your organization can vary because user groups vary you know if your user groups are you know if you're a startup that's you know primarily under 35 corralled that's gonna be different from larger scale enterprise with a more diverse group of folks so you know you may want to run some samples so maybe type testing to determine which one's going to work the best now I was really hoping to get to the point tonight where I could actually move past these list group items and actually put the skeleton itself in place but I gotta go cook dinner because folks around here gotta eat so I am going to wrap up the livestream for tonight and the next time we dive in I'm gonna pick up where we left off and I'm gonna try and get the skeleton the actual skeleton put in place and start throwing some CSS styles in to hopefully really improve the overall user experience so yeah appreciate you guys joining in and hope to see you next time let me know what you think
https://www.youtube.com/watch?v=Ll0tokkeH34