logo

NJP

ServiceNow Widget Best Practices | Share the Wealth

Import · Jan 13, 2022 · video

okay welcome everybody boy last last week we had a lot of people and also how fun widgets were and i'm sure we're gonna have everybody back this week all right let's just jump right into it all right well if you didn't join last week my name is jeff pierce very glad to meet you if i haven't met you before i've been working on servicenow for about 11 years most of that time has been portals and custom maps and fun front end stuff so that's that's kind of my bread and bread and butter and i love to to share what i know so always happy to do these share the wealth last week we got into widgets and we just started from scratch started building a widget from scratch you know kind of went over the basic anatomy we talked about what each one of these things is for and if you remember from last week as we go along i'll be talking about best practices and everything so we'll we'll be talking about a lot so take notes for sure i don't have any kind of presentation prepared we're just going to to be going through all right well let's just jump into it last week i said that we were going to to get into repeatable components like directives and stuff this week but i realized that's we're getting ahead of ourselves there are still some fundamentals that you're going to want to know about widgets before we get into all the really fancy angularjs type of stuff and so today we're going to be just focusing on getting data from the server now last week we did this here on the server scripts and and we sent this to the client controller and that's how we got data from the server into our template but what if you want to get additional data from the server or what if you want to write information to the server right what do we what do we do after the page is already loaded and we want to communicate with the server so that's what we're going to be talking about today any questions or comments before we get into it anybody all right very cool i'm going to close our preview down we're not going to use it here we're actually going to use we'll portal open here in this tab to be debugging today all right so let's just recap a little bit last week we set up this widget to get some incidents from the server and then we printed them out so let's just let's go right into it you see i already i started doing a little bit before the call here to get ready here so let's just go right into our first hypothetical situation right i'm looking at this page of incidents as the user and somebody goes and enters a new incident or they close an incident or something right something in this changes on the server how do we make this page become real time right this is one of the awesome features of angularjs and the angularjs framework in the service portal is that creating these real-time features and pages becomes super simple and especially since we have this awesome util called record watch that makes it even easier if you're looking at just simple data table data right so record watch is part of the sp util service this is a service created by servicenow for this just it contains different handy things that you can do in your client controller i'm not going to get into them all but we're going to we'll use record watch now right so this is not a this is not an out of the box angularjs thing this is a something that the service now built to be used using angularjs and what it does is it watches well you can see here we're going to pass this into it the scope that's just going to kind of be default you're always going to do that there table name and your filter and then you can run a function that responds you know have a function that responds to whenever we have changes in this table so what this does is it sets up a watcher server side so it watches this list essentially anytime it changes it's going to return to us this information so let's go ahead and just we'll run it and we'll we'll look at the stuff that comes back here and you know i'm actually going to do this a little bit better here so that we know exactly which one is which all right and actually if we want let's make this more configurable instead of hard coding these in here all right we already have these defined over here so let's just grab them all right so i gave it the table our query all right then we're going to see what we get back so let's just make sure we got a fresh page here all right 104 that's our last incident here let's go create an incident all right so that was incident 105. we don't have it in our list here but look at this we got a new console here so our name you know i think we got our name and data mixed up let's i let me turn those around first we get our data then we get our name and you know what actually name is coming back as undefined half the time i don't even know what that one is so let's just we're just going to work with our with the data let's not confuse ourselves with name right now all right all right but let's go ahead and look at this so this is the data object so you can see data data we could see this is a new record that came in so action entry the display value the sys id so this is the record that just got entered right which is now what is this one ext i actually don't know what that is so let's not worry about that right now so that's pretty cool right we we got with just a little bit of code we were able to watch the the incident table and know exactly what got entered now what if we want to actually update our list we have this another service now feature this server object or the server class whatever you want to call it this has a couple of functions that you can call with it in this very simple example with this widget where we're just showing one list from you know one data set server.update is going to work perfectly so if i bring this in here let's save that refresh our page look there's our 105 right that showed up because that was inserted but it didn't show up until we refreshed the page so now let's put a new ticket in look at that before i even got there it was there i didn't have to refresh isn't that nice boom super simple that's awesome so these two things right here are going to be incredibly useful to you for creating these these these widgets that stay up to date right and it should almost kind of become a best practice or a standard for you that any any widget you build that creates some kind of list or data you're going to implement this record watch to keep that list updated any questions so far on the record watch hey i'm not i'm not sure if you explained it last week but does everyone understand what server update is doing no i didn't i'm going to get into that okay cool cool yeah yeah we didn't do that yeah i'm going to get more into this one now anything else though all right all good let's yeah so let's let's see what other ways so so this is an automatic way right this is this is great but what if you have just you know more let's think of an example some other data we can pull in let's just continue with the incidents we'll do that let's do this let's say we wanted to well let me just explain this for a second yeah well this is a good spot to explain this david so server.update what this does the simplest explanation is it's going to take the data object from your controller you know which is essentially scope.data right and it's going to send this over to your server script and over here it becomes input object rather than data object and then when you when you call update it's going to run your server script again so so here let's let's do a couple of things here here you know we're just going to we're going to create a button here ah we're just going to call it update all right then we're going to create a function over here called update and in it we're just going to call scope.server.update and we're going to see what happens but first over here let's do two things server script start then if input we have an input and then we'll go ahead and log it all right so let's watch what happens here refresh the page alright we got our update button let's click it all right so let's see what happens so before i clicked it we got this at the beginning right because this is going to load as soon as the page loads so we got that at the beginning of the server script all right then we clicked it and look it ran again so we see that it ran the whole server script but it also included the we have input part which it skipped the first part because there was no input does that make sense and look what came back the same data object right the same i mean it was the same data object that got sent to the client script but it was the so is nothing changed in it so it's the same one that came back but let's watch this let's add to it scope.data dot pizza equals true and actually first let's go ahead and blog client side scope.data let's refresh that okay so you can see the server script ran and then this client script ran there's our data you don't see any pizza in there anywhere we're going to update now let's check out our data object right actually this is our input object because we changed the data object client side we added pizza equals true and so we can see server side we now have that in the input object is that clear there when i call server.update it's going to take my data client side data object with all the changes that's happened to it if any send it back to the server script and that becomes our input object so update works nicely in these simple examples what if you don't necessarily want to update your list maybe you just want to interact with the server you want to send data to the server very selectively then we have a cool a very similar function called get server.get so here let's let's create a new function called insert and when we call this function we're going to let's take this step at a time here let's change this to insert and before that we're just gonna have a very simple input for a description and what's wrong with mine isn't it like that it's because we don't really need to close out of there we go all right let's just make sure this looks okay all right we don't need anything too fancy here okay so first thing we we want to do is make sure we're we're getting our value let's see click insert model so i'll stop right here and just kind of explain a little bit about what i'm doing before i get too far so with this input i'm binding the the value of this input to the variable description which is scope.description in my controller right so whatever i type into this it is going to keep this input and this variable bound together right so when i click ins insert i i actually i shouldn't even have to pass it in there right because we have scoped out a description i'm just gonna gonna log that so let's just make sure we're good so far watch this watch our console over there and i'm going to say hi there good see that that's exactly what we wanted hi there so we have our scope.description so we're going to use scope.server.get to like i said more selectively interact with our server script so here's how i always do that and to tell you the truth i almost always use dot get over dot update just because one dot get is very easy to use and i think it provides a lot more control than dot update and to be honest i can't always get that update to to do what i want it to do so there's that so here's how get works super easy let's here's our pattern this is our pattern right here actually it's sorry so we're going to call get pass to it our input right because maybe i don't want to send over the whole dang data object maybe i just want to send over a few things and you know like i said very selectively do things [Music] action is insert record actually i don't oops i don't need this all right so this is my input right insert record and right this is you'll see what we do later right this is all defined by me they're not calling anything that exists currently so i'm passing that object in all right so so that right there let's just take this part right over here that's going to send input over to the server script right so now my input is going to be an object let's just check it out now and also notice this this log line right here server script starts let's see if that runs twice let's refresh all right i ran once what we expected hi there insert oh actually it does yeah so so even when you call get your server script the whole thing runs again and of course input ran right because we have an input and there's my input object that i sent over right so input wasn't the whole data object it was just what i sent over so if you are going to be using get then you may want to do something like this if if i don't have an input then just return don't do anything but then i would all i would want you know of course and if i do then i am going to do stuff so this is a good pattern for you to to be familiar with if no input maybe i don't want to do anything at all but in this case actually i do but if i so say if no input get records then i'm going to put all this other stuff in a function called get records oops where'd it go there we go okay so now we're because now that our server script is starting to get a little messier we need to make sure we keep it nice and clean so here's all our initializing stuff let's make sure that that comes up here now actually we probably really want to do that on initializing too so if we don't have a or you can even do this here function initialize and we're going to put that stuff and then we'll just be so now we start to get a lot more organization and it's a lot easier to read what's what the heck is happening in our script okay so now yeah let's stop here for a second and make sure that we're still everything still works right so what do we expect to happen we expect when this first runs we're going to get our incident list right if i click the insert button whatever i have in the input it gets sent over and we're just going to log it for now so let's just make sure things are still still working all right looks good so far pizzas perfect all right oh you know i forgot to then uh return there we go all right so now let's actually let's let's do a little more so say we do have input input.action equals insert then i want to [Music] insert record and then we can write a function and then we're just going to do something very similar to this we're not going to do any of that instead we're going to initialize all right right now we only we only have that description so we're just going to let's just do this record now if if this was truly like configurable you could pass in any table i would do a lot of different stuff let's just pretend we're only dealing with a incident for now actually we would do set value caller id and then let's set the value of short description to what we got back from the input value all right and then we will insert it here i actually will test it if if it inserts if it fits i sits so then we'll also just do something like this to response equals response so all right so i wrote it just very basic function that's going to insert an incident and bring me back that the glide record of it and so we expect to get this response that we're returning as a response here actually you can call this and we'll just call it r so let's oops okay let's give it a try actually first let's also lock put some logs in here too just so we can kind of watch along the way how everything works always a good idea so insert record so we know we got there we're going to try to set these values here let's go ahead and put the input value there okay and then let's just log also our display value if we got one okay let's give it a try now pizza insert all right let's see what happened we got a response back but it wasn't the response we wanted at all so we didn't we didn't get any of the logs we wanted or anything so let's see what happened like we didn't get that one did we forget to like i think the function's not returned this one you didn't return anything to the front end well that's what's supposed to come back here's our response oh you know what i think uh sorry data dot response also input.action is insert on line nine in the script but over on the left you have it insert record two that's it that would help also thank you all right oops what was i doing with this data is yeah let's just delete that and then yeah i actually don't think we need to return anything we just i think we can just just yeah we just reassigned data yeah yeah so let's watch this here we'll see what happens now team effort all right guys it's pizza oh we got our hey there we go somewhere though didn't what did what it didn't like invalid table name so let's okay so it's that should be an easy one to fix invalid table name data table oh let's see what it thinks data is at this point once we are in here that'll be interesting just make sure that we're still dealing with an actual let's see here so when we look at that okay i forgot about that so when you're using get and we come back here right we our data object is empty and this is probably why here you know let's not uh let's not actually do that within a function i think i've i'm messing things up there let's just go ahead and just put that up here so we make sure we have this data this data should be available no okay so i guess it's not making sense to me but i guess data is not available there so [Music] hey jeff if you set data equals input data equals oh yeah yep yep i could do that too well here this is what we'll do here look at this over here in our input data we'll make sure we also send the whole data over that way over here if we have input then data equals input.data there we go oops so let me undo some of the stuff i did over here okay so see how that works all right insert record look at that we got one number seven okay and you can see here's the oh that's our record watch that ran right that's still sitting in there but this is the response that we got back here this object right there wait where is it this isn't quite what i expected let's take a look at that log again here and let's also clean up our logs it's always a good idea to keep your logs clean so you're not getting a bunch of useless stuff okay so what we want we're very interested in this right here let's also just comment that out for now so when we call insert record what are we doing we're trying to set data.response to record gr but over here we didn't get anything did we all right let's try it again so what we would expect is that we're going to have r.data.response over here on the server after we insert this let's just give it another try very fast all right this isn't giving us the results i would expect so let's let's here let's back up a little bit and debug what we've got going on let's comment all this out right here because i forgot we got this server update going on up there that might be kind of messing with things also let's try that yeah why are we not getting that let's see here so we insert the record you know what let's not use response let's use your record how about that and then after enter this make sure that we got that property and then we would totally expect that to be so there's the new record but it didn't get it make its way over here i don't use get all that often what is it supposed to return well it's supposed to bring back the updated data model and the response which is but it's not working that way here maybe yeah console logging just data because i know update returns the full data object even without having to use it as a parameter all right can i get it i'm not sure what get does yeah we'll get as you can see get will only selectively send over an object and then it's supposed to only selectively you know it doesn't update the whole data object when it comes back you so gotcha okay let's try it again here and you know and if we're still having trouble we're just going to move on from this part i don't want to spend too much time on it yeah very strange i don't it's bringing the whole widget over is what it looks like huh yeah the response well it that and that is the response and but it's you know it's the data object of that widget that we're expecting so okay i don't want to spend too much time on i'm trying to debug this one us let's see where to move on from here but as you can see i mean it is you know it is sending our our data across so if you if you do need to send data to your server script and take action that's super easy right we're able to do that and this really isn't that hard what i'm trying to the you know actually let me make shh let me just double check it's always good to reference other widgets let me just make sure i don't have like some funky syntax off or something so we're just gonna look in our other controllers for things with a server.get oh give me a break that ain't true oh no asterisk here let's look at my fancy form this is another one of my widgets where i'm using that successfully let's take a look get server.get yeah so you see same exact pattern i'm using over here i define my input server.get i send it over and then we've got the response that gets sent back which is here let's just double check what we're doing over here on my client my server side so if input input action yes see i'm just updating my my data model so something goofy is happening right and i don't want to waste hard time debugging it right now but this is this is the proper way right you could do this in your instance and it should give you the results you're looking for i don't know why mine isn't working so we're going to move on okay we got 20 minutes left there's one other thing i want to spend time showing you here then i just kind of want to open it up to questions for the rest of the time and that's the http service and for that i'm going to show you i'm just going to show you this this widget here this fancy form widget that i i've built i'm going to first show you the an example of where i'm using http and why uh then we'll we'll try an example with it all right so i built this nice new version of autocomplete reference fields that you know works on top of a catalog item and so in this let's see there's a spot where we know so when you type into the field we want to go you know get what all your choices are so we're doing that right in the front end so you actually don't need your server script at all right check out what we're doing here see my my function get choices from server i build a url using the now api format right this is the name of a table right there define my query you know there's all kinds of other options with this there's you can check that out but then i'm going to use the http service here which notice i have to inject into you into my function that's out of the box and yeah you just call the get you get your response and it's pretty easy so let's actually take this and we'll try in ours so let's say instead of we're just we're going to call this get now we don't need an input or anything and you know what and let's not even get our records down here anymore whereas initialize we're not going to populate the items here on the server side let's take all that replace this table scope that data dot encoded query right now we call it yeah let's not worry about any of that for now let's set it at a limit of 10. okay and so we're just gonna we're just gonna start by logging our results oops backwards all right let's see what happens what could go wrong right so we're not getting them from the server any from the server script anymore so when we load this it should be blank and even when i hit get it should be blank but let's just hdp is not defined what didn't i do the thing that i said i had to do right i told you all i had to do this http in the inject that all right let's try it again get we got something what's our response data to look at that we got an array of something incidents it looks like amazing let's let's oh yeah we can put a the order in our query can't we if i were to do that can't that be like ordered by i can't remember can we let's try and actually let's just go ahead and do this so that's data.result we've got our array and we've got every field name in there so let's just do this and and once we get that back for whoops what just happened i'm gonna say scope.data.items equals response dot oh what was it result yeah a response no response that data dot result okay response dot data dot result okay then over here it's not going to be this format anymore because remember we were doing that especially in the server script before so here let's just do something else here let's just print the numbers out make sure see yeah just got a number filled yeah item down number all right let's try it out see if it actually populates our list get nice it's pretty awesome is this it's not sorted though no it is is it no that's not sorted right why not didn't we [Music] let me close that wrong way and if we took that out do we get a different last same list all right so i don't know if that works but you you can check out the api for that we're not here to learn rest api but yeah but check that out that was pretty easy right now i don't here get rid of that right get rid of all this stuff over here for getting those records if i can just pull the whole stinking record back with http and that was fast too right let's do that again get boom there it is that's fast and that was easy so make yourself acquainted with this method here super cool super easy to do okay so i showed you a few different ways right we looked at record watcher we looked at the server.get and the and the server.update we we just finished looking at http can anybody else think of any other way of keeping your your widget model in sync with the server via the client side that i'm not thinking of here or that we haven't talked about yeah i can't think of any either one last thing i wanted to show and this will be a teaser for next week good segue into next week so say your server script starts to get rather unruly you got a lot going on there and maybe you've even got functions that you want to use in other widgets or or elsewhere awesome way to keep your server scripts organized is to not do your server scripting in the server script do them in a script include so something that i very often do is like one of the first things i do when i start building a custom portal or you know anything rather complex is i go create a script include my portal and it'll be just like you know whatever my portal utils right and now any of my complex functions or more repeatable functions i don't have to do them here i'm just gonna put them all in my in my script include and call them here so like you know if i have that get records function i'm just gonna i'm gonna have that parked over here now i can call that function from any script include and i can pass it up to it so that's about all i'm going to say about that otherwise i'm going to start giving away david's stuff next week which i don't want to do but that's i guess that's where i'm going to end here i'm just going to open up see if anybody's got any questions or any ideas of where you'd like to go next in widgets maybe maybe next would be good to start looking at the the directives and stuff if you're all into it services services yeah services i love services services are are a great thing and and they're a little confusing to wrap your head around at first how to use them you gotta create getters and setters and stuff but once you do once you understand the pattern they're pretty awesome yeah anything else anybody you may have answered this but what's an advantage of using uh http because in this case you just could have used the server script to pull that list together right and then use record watch to update it since you're just http a table list i'll tell you here here's the the best way to describe the advantage is to show you a more advanced usage of it and that was here over where i was showing you that so so here i created a a s a directive for this autocomplete field right now this directive i want to be able to use this on any widget now the drawback of that as these directives are only client-side right so i i have nowhere to or i mean if i if i wanted to use server.get or server.update i would then have to add those into the server scripts of every widget that i want to use this directive in but here i can actually talk with the server without the presence of a server script so i'm able to now use this directive and use this anywhere i want in any widget without ever updating a server script field so that's i think your primary advantage of this nice and it never sends anything to the server it's communicating directly with an api yeah right so it actually is like slightly faster even can we call like endpoints or apis for different tools as well over here oh absolutely yep yeah you can see i just constructed my url here so you you you construct whatever url for whatever api you're you're targeting yeah so this http this is an angularjs service yeah so this is not unique to servicenow at all but since it's servicenow you don't have to worry about authentication right when you're using yeah i can go right into the api yeah so if you wanted to use a different api for something else you have to have authentication or you go set up a rest message right that does all that and then you can do the same thing here right yeah yeah which like i have done that with another client recently a pager duty integration we have a widget that that is doing this but it's the rest integrate it's the rest message that we've configured that has all the authentication and everything okey-dokey well all right all that's that's it i guess we'll end six minutes early don't hesitate to contact me anybody you know i think like i said last week don't spin your wheels on stuff reach out to us you know ask me if you got any questions david is great with widgets we've got a lot of people who have got good widget experience so portal devs or the uix coe those are great places to post your questions if you're stuck on any of this stuff so try not to spend hours figuring it out we can probably point you in the right direction because these can get pretty pretty tough sometimes but they're they're they're so powerful thanks jeff yeah you're welcome thanks everybody for attending [Music] you

View original source

https://www.youtube.com/watch?v=ASaMoLKHWM4