jQuery Editors: Rich client experience

[Infragistics] Damyan Petev / Wednesday, September 19, 2012

jQuery editors for rich client experienceOnce you get to know Infragistics’ set of jQuery Editors you begin to realize they are packed with various options and all sorts of knobs to be tweaked. It’s quite the rich API and it can be put to good use to create awesome client-side experience for the end-user. You get elaborate options, events and methods that will help you create functionality to delight or you can better adjust the editors to your page with styling and to your users with localization. That’s a lot of defaults and with just a little effort you can go even beyond that. We’ll take a look at some of the valuable methods and what you can do with them plus nifty events tricks; some combinations of default options that truly transform the editor and a DIY localized currency calculator field and more.

In case you missed the previous two articles on those here’s a quick jump list:

Getting and Setting values

So far in the first article you’ve seen simple form submit in action, which while doubtfully is a way of getting values... well, it has not much to do with the actual widgets, more with the HTML input element. That is default bowser functionality assigning key-value pairs using the form input fields’ name attributes. That is also the reason why we’ve seen an extra input and additional extra ‘inputName’ property – the second hidden input the editors use to set the actual value while displaying it in some odd format. Except that, the client side controls have little to do with the way from data gets to the server. This is something that can be changed and it’s next on the menu!

All the editors offer the value method that is used to both get and set data. Note that when setting a value, the widget will parse for you to the appropriate type depending on the editor ( e.g. number for numeric) and should it fail it will be considered invalid input and rejected. On the other hand, when using the method to get a value, you should be aware what you get would be dependent on the data mode for some controls (e.g mask or date editor). Fortunately, their data mode defaults are set up to allow you not to worry about that.

The value method:

  1. $("#category").igNumericEditor("option", "value");

That would return whatever value is currently in the editor as number. Yes, for simple numeric editors you can snatch the value directly from the HTML input, however, it will come as string. However take a Mask field with its data mode set to 'rawTextWithRequiredPromptsAndLiterals' and you get something quite different:

jquery mask editor value with literals prompts

Same thing with igDateEditor and igDatePicker - they have a mask, of sorts, by default, so what you see is not what you get as the default value for those editors is a Date object, naturally. That leads to the following result from calling the value method:

jquery editors date value with separate date format in the input field

Again, you need to be aware of those and change the data mode if the defaults don’t fit your needs. Setting values adds the new one as third parameter for the method:

  1. $("#category").igNumericEditor("option", "value", product.CategoryID);

NOTE: Passing an inappropriate value will possibly cause it to fail the parsing and come out as null. Also, if you suddenly feel a little mischievous and go for the HTML input value and set there something unacceptable, note that the editor will still be keeping the actual value and will restore it if needed upon first interaction. Just so you know..

Form submit the AJAX way

Again in comparison to the previous usage of form submit – the fact that it causes a postback in itself can be a somewhat of a user experience hiccup, definitely is for me. To address this, using the value method we can send all the values back to the server in a simple AJAX request and enjoy better page behavior  - no page reloads and if you bother to check for actual changes, reduced requests. Something that really helps when dealing with multiple editors, like I’m sure you would in a edit form, you get a bunch of different editor widgets with different names, which severely hinders the ability to loop through and collect values.

There are two solutions to this really – one being, if suitable, to pick all the values from the HTML inputs instead as they can be selected and looped through. I used this, because the receiving action in the ASP.NET MVC application handles casting the values back to their intended. Speaking of MVC, it is the MVC wrappers that can help a lot in this – for the sake of unified helper output code they initialize all editors with  the base ‘igEditor’ class and setting types. But then again that is so very much not a bad idea – using the wrappers and just in script if you define all editors like that it would be the base class used for all method calls so you would  easily be able to loop through and get the values in proper types too! Since all jQuery widgets store their data using the .data() method they can be accessed the very same way – you do need the widget name, and that’s why using the base editor makes this so easy, here’s a super simple method (more elaborate version is available in the demos):

  1. function save() {
  2.     var values = [];
  3.     $('#details fieldset').find('input').not(':radio').not(':hidden').each(function () {
  4.         var editor = $(this).data('igEditor') || $(this).parent().data('igEditor');
  5.         values.push(editor.value());
  6.     });
  7.     //send back to serv
  8.     $.post('@Url.Action("Update")', values);
  9. }

Selecting just the right inputs completely depends on your own markup really - since this save function is used for editors created with the ASP.NET MVC helpers (they create a hidden input to store the value with the proper name for you)  I need to exclude those, as the actual widget is initialized on the visible input element. Also I have some radio-s that need to excluded as well. Then you also have something specific for the MVC helpers as well – editors with the spin buttons (they are SPAN elements) are wrapped in a parent span and the widget logically is initialized on it – thus the ‘.parent()’ call when the widget is not found on the input.

Being stubborn and all…

Once you get the widget reference you can access all options, properties and methods… validate as well! So yes, you are not in any way forced into form submitting to get proper validation going on. Also, to justify the title, in my script only demo part I have initialized each editor like I normally would with their extended versions. That, based on what I explained above, should make it rather impossible to loop through the widgets, or would it? The thing is you can still search for the widget reference, so what follows is a method that would search for all jQuery Editors in the selection and call validate on those found and return a bool if the group is valid (basically to be used to stop sending the values to the server, like a normal submit would):

  1. function validateAll() {
  2.     var areValid = true;
  3.     $('fieldset').find('input').not(':radio').each(function () {
  4.         var editorkey = Object.keys($(this).data()).filter(function(x){
  5.             return /\big[A-z]{0,8}Editor\b/.test(x);
  6.         })[0];
  7.         //trigger validate and if no false has been met assign the result
  8.         if (editorkey) {
  9.             areValid = $(this).data(editorkey).validate() && areValid ? true : false;
  10.         }
  11.     });
  12.     return areValid;
  13. }

Lines 4 through 6 would loop through all the property keys of the object returned by .data() and find the one that match the regular expression above (basically anything like ‘ig*Editor’ will pass) and take that key and use it to get the widget reference. The rest is simple call to validate and retaining false value if ever met, but the point is this way of getting the key can be reused for any functionality that seeks to find all the igEditor-s.

Invalid input behavior

One particular thing that I found different from other platforms’ editors is the lack of readily available invalid behavior (perhaps it can be added by popular demand, eh? what do you say?). Still the fact is that this can very well be achieved be handling the default editor events such as the ‘value changing’. Notice the ‘-ing’? Means this even can be canceled and if it is, well the actual change is as well! That means you can override the default set min/max value behavior by rejecting the input and leaving the old value instead!

  1. $("#category").igNumericEditor({
  2.     dataMode: 'int',
  3.     maxValue: 8,
  4.     minValue: 1
  5.     valueChanging: function (evt, ui) {
  6.         if(ui.value > ui.owner.options.maxValue){
  7.             //ui.owner.value(ui.oldValue);
  8.             return false;
  9.         }
  10.     }
  11. });

Note that there are two ways to do that – cancel the change or change the value back. The latter can be used if you still want your ‘value changed’ to be fired.

Now with more… spinning!

jquery editors numeric spin buttons

One other favorite feature of mine  - the spin buttons. They are very easy to set up and provide quite the functionality out of the box. As you would expect for a numeric-like editor (Yes, yes, date editors included!) the spins with increment/decrement the value by one (the default for date is also one day). The spin buttons can help the end user quickly and sometimes more precisely get to the proper value. For that to happen, of course, the settings should match the usage scenario, but let’s say we want to go through a lot of values fast. The ‘spinDelta’ can be very helpful and the user can actually hold a spin button down and the speed as with value changes are applied gradually increases to a quite high rates!

Another extremely useful feature which you get out of the box – spin wrap around! What it does is when the user attempts to spin beyond the defined minimum and maximum values (normally that would do nothing), it allows that action to move to the other end of the value list – from max to min and the other way around, basically a rewind for the values. So lets improve on the editor code showed last by adding the spin buttons with all the enhanced functionality:

  1. $("#category").igNumericEditor({
  2.     dataMode: 'int',
  3.     maxValue: 8,
  4.     minValue: 1,
  5.     spinDelta: 3,
  6.     button: 'spin',
  7.     spinWrapAround: true,
  8.     valueChanging: function (evt, ui) {
  9.         if(ui.value > ui.owner.options.maxValue){
  10.             return false;
  11.         }
  12.     }
  13. });

But wait, there’s more to these buttons:

jQuery text editor with spin buttons

Does that look awkward in any way? It looks like an editor with spin buttons but with text in the field?! Since this is a custom input implementation that does not use any part of the HTML input (of type number) the spins are not limited to just numbers! They can be instead used on even the simple text editor that has a list of items. Yes, that means you can provide a set of items and the user would be able to loop through them using the spin buttons. And wrap function works here(..and well you can change the button property to dropdown to get those in a list even, more on that in the future):

  1. @(Html.Infragistics().TextEditor().ListItems(new List<string> { "aspnet","jquery", "ios", "reporting", "wpf", "sharepoint"}).ListAutoComplete(true).ListMatchOnly(true)
  2. .ButtonType(TextEditorButtonType.Spin).SpinWrapAround(true).ValidatorOptions(validate => validate.OnChange(true).OnBlur(true))
  3. .Render())

Style

As you might have notice the editors have been sporting some clean Modern design (why do I always feel like saying ‘Metro’?). Even with as little screen real estate as these controls take, you can still tell it’s pretty – sharp edges and colors, nice effects (especially of the validation messages and oh my don’t even get me started on the date picker). Go see them on the Editors Windows UI Theme Sample! And you can also use them with custom styles!

TL;DR | Summary

Stay tuned for the second part and DEMOS! When I mentioned something about a rich API it was no joke – so far some of the things showed above might’ve been more appropriate for the ‘guiding the user’ blog, but hey they just won’t fit, and at the end of the day those jQuery Editors’ job is to make both the user happy and the data reaching the server good, so almost everything overlaps.

So far we’ve covered how to get and set values, how to send them to the server without causing a postback via AJAX. Also on the list was how to get widget references for multiple editors and possibly using this to get values and/or validate them. I’ve mentioned some ASP.NET MVC specific differences that should be kept in mind, like events. The latter you can use to exercise better control over the way editors handle invalid input. You can also delight users with spin button functionality that would also work with predefined text values and and top it all off with some looks with themes and custom styles.

And I’m leaving some pretty neat tricks with localization and validation for the second part of jQuery Editors experience!

As always, you can follow us on Twitter @DamyanPetev and @Infragistics and stay in touch on Facebook, Google+ and LinkedIn!