Servoy UX patterns: Look-up form
Servoy UX patterns: Look-up form
Hello, and welcome to another 30 minutes with Servoy developer series Good morning. Good evening. Good afternoon. I am a Steve Portonoy. I am with Servoy and we as always as Sean party on Sean party on Steve This morning we’re gonna be discussing UX patterns look up for him, but before we get into this I did want to say something Which is thank you to everybody who attended our 8.2 launch series We had a great turnout for that and a lot of great response during and after and if you missed any of them as always You can find recordings of each of the webinars on the Servoy forum under the announcement thread In addition to recordings of those webinars. There’s also links to the wiki documentation and sample solutions and anything you might need to Review and or get caught up on those So again, thank you very much to everybody who attended those and thank you to those who are attending today’s with that I’m going to hand over to Sean Thank you. Oh, I’m sorry before I go As always if you have questions, there is a questions panel in the webinar If go ahead and type your questions and either during or at the end we will do our best to get those answers All right, is my screen visible? Yes Yeah, and to the point about the 8.2 stuff If you haven’t seen it catch up now because 8.1 is coming out and there’s there’s new stuff in extension. So it’s a Never ends Today should be pretty I think concise and fun. We’re going to take a look at It really just a UX pattern That I think I see in loads of business applications And I was working with a customer a couple customers that needed the same pattern I thought well, let’s make an example of it and it sort of turned into a little module And I thought of this is great for for the tech webinar series So this should be pretty short concise fun. It’s really a mash-up of of Servoy tricks too, so For me doing this was kind of an affirmation that Servoy really is a Still a productive platform to to make the UX that you want because I got to just sort of cobble together a bunch of tricks and and extensions And get this this this UX pattern. So We’re just going to do a quick demo of what it is and then we’ll we’ll sort of Step through the code and then and then just do a quick overview of what we have just seen so I’m switching over to the HTML5 client and just a quick overview of What this UX pattern is Let’s say you want to select I don’t know a product and Typically you might put a drop down like combo box or a value list on a form But what I’m hearing is from time to time is hey, we want to be able to show Multiple columns say in the drop down rather than it just be you know the type ahead and you see the one value showing up or the Catinated two values from a value list. So I hear sometimes we want to be able to see Multiple columns perhaps related data from other tables also the search portion the type ahead works mostly on Typing and you get sort of the starts with thing but maybe you need a bit more complexity of the search like you want to be able to put in Several words like an internet search and it’d be tokenized and then you really see the matching results So let’s take a look. So I’m trying to pick a product. I click in here to this component choose a product and You see that here instead of getting a regular Type ahead I get a grid presentation and I have more than just one column I have the product name But then I also relate over to one table the category to show the category and then also over to The supplier of that product. So if I want to search on say the company name who supplies the product. So Now I’m going to type a few keystrokes and You’ll see as I type Let’s do beverages and then I’ll do a space and then so the search gets tokenized by by words and then I’m going to Type in BIG and you can see that I get beverages and I also get big foot breweries from the category in the supply And then I’m going to hit my arrow key down and Select the logger and hit enter and you can see that selected so you could do You can just type and you never have to leave the keyboard. You can arrow down. I could also See food I could also use the mouse and scroll Through and this uses the grid component. So it’s got really fast Scrolling and I can use the mouse to select as well. So that’s really it for The UX pattern Let’s let’s go ahead and look at how it was done and the thing that’s interesting about this is it’s not really A new component to do this. It’s more of like I said a mash-up of existing tricks and extensions so I’m going to go under the hood to serve way developer and Have a look at this form Test lookup so here you can see on this form. I have I have a component on action It’s a it’s just a field and on action. I have this select product method and I made a little API Called sfy look up so I’m creating this lookup object and I’m adding the fields to it so the first thing I do is create the lookup object and I pass in the data source In this case we want to look at the products table and then I start adding the fields First I want to see the category that’s related I’m also setting the title text so that’s that’s what goes on that’s what goes on the column And then I do the product name and the supplier and so you can see that This is an API that will generate code complete so as I add the field and the data provider then I can do things like set the title text or the value list Indicate whether or not it’s searchable so I could let’s say have something on there which is Which is Even the display, but I don’t necessarily want to search on it as well by default everything that you put on there is searchable So what you see is what you can search on Okay, so Then once I’ve sort of created this lookup objects which is sort of an abstraction of You know what I want it to you know what I want to show what the data sources and what the fields are Then I just want to show it so I want to show it relative to a component So it drops down right below that search box. So I just that that element is called product ID And then in this case I’m I’m seeding it with an initial value So if I have something Already selected then you can see it goes in it It’s so it selects that in the list there. So I’m able to see it with that initial value if I if I didn’t put anything there then It would just go to the full the full list and it would be a blank search criteria so Then finally I call this lookup object show pop up and if we look at code complete here You see that it’s an overloaded method so At a minimum what I need is the callback the function that will be called when the pop up is Is when a value inside the pop up is selected and then the target the component that you want to show the pop up on In addition to that you can do With height and initial value I’ve chosen to do null for the The width and height the width will then be taken to match the component that you’re showing it on so it lines up under there But you could actually pass in an arbitrary width and an arbitrary height the height is Also like an arbitrary default that is used, but you could override that so if I wanted to for example make this 1,000 pixels wide and 600 pixels tall and then I come back here You can see that now the lookup is much bigger so it’s immediately can be editable So Again, I show the pop up I pass in the on select function Which receives the callback after a value is selected so You can see that here its passes in The pop up in the generic sense always passes a j s record object back However, I’m in the type tag here and the param tag here I’m casting it as a as a product’s record because I know that that’s what the data source is that I used Therefore, I get code complete on product ID And I’m just setting that back to that form variable that data provider to which that initial field is bound So that’s that’s pretty much it at a high level um If we jump into this This sfy look up scope And I look at the outline here You can see that there’s really two classes look up and look up field And we called create lookup and then you can see The outline the the methods on the look up itself and then each field in the look up This is just sort of an abstraction of what you want at the end you call show pop up and It’s using a default implementation and this is where we get into um Some form inheritance we we have a form called abstract lookup which Is nothing but it has it has some of the blueprint for Showing the lookup and then we have the sfy lookup table Which is one level below that and this is essentially the form that’s being shown now The reason I’m showing this is it’s it’s nice if you just want to take the the little module and use it as is But if you wanted to extend The form and Customize it in a way that you like maybe you add some buttons to it for you know closing it or something like that But we’ll come back to the form inheritance stuff If we look at the show pop up method I Just want to point out Because I thought this this was a really good example of you know, I put this together inside of a day um You know, but now it’s a reusable Kind of pattern I want to show sort of the ingredients so it’s a bit of a learning exercise and what went into it So one of the first things is is to show a form in a pop up when we get the pop up here You’ll notice that as it pops pops up if I click away in the body of the form It’s dismissed So it’s not really a dialogue or a modal dialogue It’s not as heavy and it’s got really that UX that’s more common to web applications where you don’t have multi-windows and dialogues You have things popping up and and dismissing easily so The main ingredient for that part of the pattern is the show form pop up method of the window plug-in So this is already something that ships by default with With Servoy and is available in In all the client offerings so the smart client and the HTML5 client etc And really what this what this takes is the form that you want to show The first thing is the component you want to show it relative to then the form that you want to show and It does have the ability to To To bind to a scope and a variable In this case, I’m not using that. That’s why I’ve put phoobar in there and then this So I could show a form pop up and then When you when you when you when you close the form pop up you can just return a value and it will automatically assign it to that I find that that’s a little bit inflexible so what I do is I do a callback So you can see that what I’ve done here is for the first argument of the show pop up method in the base form It takes a callback and I sort of store that in this variable called selection handler and When we dismiss the pop up or when we select in the pop up We just proactively call the callback and pass the value back because in this case I want to do a whole record I don’t know maybe the caller wants to take the record and do something with it In this use case, we are writing it back to a data provider But I feel that’s a little bit limited which is why I just made the callback instead so Then it’s the the same options as before the width and the height That you can also set so again, that’s on the window plug-in show form pop up and it’s it’s just standard functionality You get with Nearly every version of Servoy The next thing you might have noticed is that This is running every keystroke so as I type Every keystroke is sending Moreover as I hit that I’m going to hit my down arrow key you can see that I now have focus on On the table and I’m able to arrow through those and when I hit my enter key I’m able to select a value also if I’m Showing this and I hit the escape key. I’m able to dismiss it So there’s a little bit of keyboard interaction going on there and I’m able to get that mouseless Kind of feel on this pattern and I want to show you the ingredients for that so the next thing I want to look at is the key listener The use of the key listener extension so Think that’s over here You So the moment that we focus on the field I’m I’m adding a listener Basically what I’m doing is I’m setting a little flag if I’ve added it yet or not because it sort of gets removed automatically Every time the form shows so I just want to add it once So I use this little key listener ready flag which is just a form variable But the real line here that you want to pay attention to is this We have a whole other webinar about this particular extension, but this is If you’ve missed that just a 10 second recap This is what we call an NG service which is allows you to invoke some behavior in the browser And it’s exposed as a plug-in So the key listener Service allows you to attach a callback function To receive events every time a key is pressed on a target component Okay, so I’m adding the key listener to the search box on that Lookup form that’s being shown in the pop-up and I’m using this on key event or Handler to handle the event so if we look at that You can see this passing in a number of arguments and I want to point out to those of you who are Already familiar with the key listener. We just added these additional arguments and this is available in the latest release on the key listener ng service so Initially it was just sending back the value of the component so as you type it would send back the full string that’s in the component as you’re typing But in this case I wanted to be able to handle the down arrows So I took the key event and I passed back more information including the key code And the alt key so if there was some some modifier attached to that As well like a shift or control or something so The key code 40 is the arrow down key so I’m just handling that it could be You know that’s some sort of arbitrary But I think that’s common when you’re doing it that look up sort of pattern So if I arrow down Then I’m handling that and I’m just requesting focus into the table and then and then I’m done otherwise I want to run my search on the full value that’s been typed so So that’s how we were able to do the the searching as we type now for the search itself We use another extension but before we get to that I want to go to Two other things that you may have noticed One is that when I hit enter I’m selecting the value and the other one is when I hit escape I’m dismissing the pop up and I did that a little bit differently You can see that when the form is shown I’m also creating keyboard shortcuts and this is again on the window plug in the same plug in that that shows the pop up So this is standard functionality You don’t have to include any extra libraries to get this and this works in the browser as well So you’re able to attach a listener or a callback you know function to handle When a short keyboard shortcut is Is typed so in this case I’m binding to the enter key and the escape key and you’ll notice that I can attach a function so I have on enter and dismiss and as well as I’m passing a controller get name Which is the name of the form so The third argument in that that call is the context so that You can leave that null and you have sort of a global keyboard shortcut that is available at any point in your application But here it’s just really specific to To this form so when this form is showing Then I want to handle this when this form is gone Then we don’t want to handle this anymore And so that gives me that level of granularity If we look quickly at the on enter This is where I did a bit of testing here I can remove that But this is where I call that on select which then Calls my select handler so you remember I was storing that function and we pass this back so Anyway, I just wanted to point out that that’s that happens When we do the the on enter Same with the I lost my my place here Oh, I’m in the the base form. That’s why Same with the With the escape key in this case. I’m calling the dismiss function and That is Also in the base form And that just closes the form pop up so That’s the same as when you click out so I just wanted to point out window Plug in add keyboard shortcuts gave me that additional functionality once the the pop-up has been shown Let’s get back to the search. So Remembering that as I’m typing keys I’m calling that search method and passing in a string Of what the user has just typed In the base form. I have this method search And you’ll notice that there’s not a lot of code So if you haven’t learned already There’s a module to help with that that’s called SUI search It’s one of the most popular extensions that we have out published on github and available through Web package manager And really what this does is it’s saying, you know first of all if there’s there’s no value We want to load all records Otherwise, it’s using this API called SUI search. We create this simple search object We set the value that was just typed I give it the ability to just search on all text The default is no, but all text columns can be just made searchable with with with one line But in this case, I think it’s more intuitive that we’re only searching on things that we can see Therefore if you type something and then you get a match and you don’t see it. It’s a bit unclear So the default is no And then I’m iterating over that I have that lookup object that I initially have shown And I’m iterating over it and I’m calling this add search provider and really When you call this you can pass in a data provider and then you can do a whole bunch of other stuff You can set an alias you can set Case sensitivity etc. So that that in and of itself is a whole other library and it’s just for text-based kind of semantics when To when searching so it’s low code no sequel kind of thing so Just wanted to point that out That’s how we’re doing the search and that’s also in another webinar and there’s lots of other resources about Okay So let me just jump back to The presentation here and just kind of show you what went into this If we’re going pretty fast and there was a lot of different things I showed you if you get none of it Or very little of it. That’s okay because we’re gonna publish this as a standalone module Which is something that you could just Download and use you can just call the you know create look up and then show pop up and that’s it and and just use the basic Implementation, but I just thought that since this is the tech webinar series it’s a good excuse to kind of show the ingredients that went into that because You know when you want to make your own user experience pattern there’s a lot of different Tools that you’re disposable, but maybe it’s not intuitive or immediately Understandable how that you would you would integrate those you know Together to produce the end result. So this is the list of the ingredients that went into the the UX pattern And if we look at these individually just to recap Again when we showed the form in that that dismissible pop up We use the window plug-in calling show form pop up and and there we’re showing it relative to the component that was clicked You have the option to set a data provider automatically in in my case I used to call back because I think that’s a bit more flexible So I passed in a function I stored it and then when when they click or when they hit enter We’re calling that function and passing the record back into it Another thing was was that I was searching on every keystroke And so for this I used the key listener Which is an edgy service that’s available through The web package manager and it gives you the functionality to handle keystrokes on any component And now it’s just been updated to receive non-text keycodes and modifiers So that’s how I was able to handle the down arrow to get back down into the Into the table component When we’re doing the search we used another extension here also available through the web package manager The s who I search module and this as I said before is really one of the most popular And most used extensions that we have because it’s very generic and it’s really low code You don’t have to do any SQL stuff and it has a pretty robust API And it has a user interface that’s very intuitive because it just takes Simple text and it tokenizes the input based on words You know separated by space and it allows the developer to just say I want this data provider that data provider that data provider That data provider and then and then that’s it they’re done We also use the keyboard shortcuts which is again part of the window plug-in so that’s how we were able to handle the enter key and the escape key to dismiss To select or dismiss the In the pop-up A couple of useful links here that I’ll leave up as we take any questions We’re gonna post this as a little helper module on a repository called sfy look up I’m gonna do that Later today after the webinar Already you can go get the latest version of sfy search or sfy key listener Those are available through the web package manager As always you can watch recordings of this and others On the tech webinar series homepage and please post your feedback And look for announcements on you have a dedicated forum thread on informed us or void.com under the announcements category And that’s where we post also links to every webinar recording and slides and Example solutions Steve, do we have any questions? Yes, we do first of all great stuff. So a couple of questions from Quail And the first one Actually ties into a question that I have Actually her second question. She says it works well in the web client. Does it also work in the smart client? You sort of answered that with the show form pop-up that the show form pop-up does work in all clients. What about the key listener? Does that only work in the ng-plan So Yeah, so the the the complete example that I showed here Only works in the ng-client however you who get the same UX in the smart client with a bit of a different mix of ingredients So the key listener is ng-client only but there’s a key listener plug-in for the smart client Just so just because the smart client is Java swing it needs a bit of a Different way of adding that so you can get that also The grid component was used The ng-client grid component was used in the babies form But you could make your own base form which extends the abstract lookup base form and has the And has like a table view form which is also compatible for smart client So Quail no and yes, you can’t what I showed would not work but Could be easily modified or adapted to run the smart client Great her other question was does this have the same record number limitations that a drop-down has which is currently? She believes 500 records Ah, okay. Yeah, good question. So No, not at all the the number of results is is actually found set based so It’s more like when you work with a form initially. It’s limited to 200 But if I had more than 200 results as you saw as I was a arrowing through the the grid It would do the infinite scrolling thing or the pagination thing depending on how you haven’t set up So it’s not limited A couple of other questions from Steve, where can we find a table of key codes and alt key codes? I had the same question myself when I was starting this I just did an internet search. I think that I could have I did 40 I just was being lazy and and if I When I when I published this I’m going to replace that with with a constant. I believe in In Java there’s an enum so you could just reference the enum directly to get the The key code, but I’m not exactly sure where that is But there’s it’s probably all in the Java documentation and when I published this I’ll replace the 40 with a constant. I think Ram is posted that you can find them at ask key table.com which I am not bare have not verified But I’m going to go ahead and post that URL in the chat window to everybody Okay, so that’s the answer to one of his questions. The other question Steve had was can it do multi select? Yeah, so it could I wanted to get the multi select Working for this example But I ran out of time So I plan to add it because yeah, obviously you might want to Show the pop-up and then click a few records and then and then dismiss it and get those records back So it could be easily adapted to the multi select and that sort of In the plans for the next iteration of of this feature How you do that in the UI? I think initially would just be Enabling multi select on on the found set and then the component can do the shift click and everything But of course you might have a different implementation in mind One other one other trick that I forgot to mention that went into this Steve also is the solution model The fact that we’re you know, we have a base form which has no data source But when we say okay, I create a lookup object now I want to show it what we’re really doing is is cloning that form and then setting the data source and then adding Columns to it to the table there. So I did want to mention all the tricks that one involved in it Just occurred to me that I left out the solution model. So that’s one other area that You would you would need if you were to do something like this from scratch
