UX Guidelines and JavaScript best practices with ExtJS
Ranjan Baisak RB
Principal Architect | AI & Cloud Solutions | Full-Stack Engineering Leader | Ex-Juniper, Ex-MentorGraphics
Messages
All messages should be managed in properties file, with message code, severity, title, description, alternate_msg
- All error messages should clearly show error details and alternate way to recover.
- Generalize messages with message code to help customer support.
- Message code can also help to replace system errors
Labels
All labels will have uniform labels across screens. Label texts will be retrieved from property file.
Non-Standard/Custom UI elements
Try to avoid any custom UI elements.
Provide Visual Clues for long running processes
- If a command takes more than 1 second, show the "busy" cursor. This tells users to hold their horses and not click on anything else until the normal cursor returns.
- If a command takes more than 10 seconds, put up an explicit progress bar, preferably as a percent-done indicator (unless you truly can't predict how much work is left until the operation is done).
Default Values
Provide default values wherever needed.
Provide examples or visual clues for User to get more information.
HTML Specifics
HTML Form Elements
- Grid Buttons order Add/New,Edit,Delete,View(optional if available) & other actions. All Button height will be 24px and width of min 75px as consistent.
- Grid with Pagination
- Search option on top right of each grid.
- Always use paging grid
- Use links or buttons to open any dialog (don’t use double clicks to open details dialog)
- Approach: Show the unique column in each row with “Blue†Color and on mouse over of that particular cell/text show the handover icon with hyper link , once user clicks the hyper link show the details screen.
- Checkboxes will appear before label.
- Behavior of Wizard based edit workflow
- Approach: While editing any Wizard based flow, take the user to Review screen on Edit and allow the user to select any step in the wizard post that.
- Mandatory fields in the workflows are not displayed consistently across various workflows.
- Approach: we mark mandatory fields with a red asterisk, and we can follow the same convention here. However, the specific problem was with related to the indication of conditional mandatory fields i.e. based on some other selection on the form, a field can turn mandatory. Suggestion is to use some Javascript to mark a dependent field mandatory (add an asterisk) dynamically based on another selection.
- Use colon next to the label-This should be done with colon separator
- Labels must start with capital
- Mark “required†with ‘*’ for Mandatory fields
- Buttons should be right aligned for the wizards-Back, next, fields, cancel
- Use Tooltip to provide help message, This option is not provided in the Ext form fields. All the forms should extend from Framework ,to get the Tooltip for the form elements
- Action Buttons-OK, Cancel should be center aligned in Popups
- Popup window should be centered in the workspace area and should not go on top of the ribbon.
ExtJs(JavaScript)
JS check for equal(== vs ===)
Use === instead of == for checking equality
- === and !== are strict comparison operators
- Two strings are strictly equal when they have the same sequence of characters, same length, and same characters in corresponding positions.
- Two numbers are strictly equal when they are numerically equal (have the same number value). NaN is not equal to anything, including NaN. Positive and negative zeros are equal to one another.
- Two Boolean operands are strictly equal if both are true or both are false.
- Two objects are strictly equal if they refer to the same Object.
- Null and Undefined types are == (but not ===). [I.e. (Null==Undefined) is true but (Null===Undefined) is false]
- == and != type-converting equality comparison
Tab panel’s lazy loading
Using “deferredRender:true†declaration you can ensure that the tabs of the tabpanel (for that matter any container using the card layout) will be rendered at the time it becomes active. This is pretty helpful when
- There is a significant amount of content or
- A lot of heavy controls or
- There are many tabs and user may access only few during any given session
Avoid Component Nesting
Avoid using panel inside panel/window. Wherever possible use container instead of Panel/Window.
Container
Base class for any Ext.Component that may contain other Components.
Containers handle the basic behavior of containing items, namely adding, inserting and removing items.
Panel/Window/TabPanel
The Panel extends the Container, meaning it can do more stuff. For example it has a header and supports dokedItems (i.e toolbars), can be closed (compare also the other events of the two components), while the container does not have by default such things.
The general rule of thumb : Use simple containers always when you do not need the features of the panel, i.e when you just need to host other children.
DOM access and manipulation
Always consider using Sencha or libraries you use classes which wraps the native javascript DOM methods, otherwise you may end up facing browser compatibility issues.
Query best Practices
ComponentQuery with root elements
Always use Ext.ComponentQuery.query with root elements.
If you don’t use root element then all Components within the document are included in the search and thus the search become costlier.
Use down/child/up methods
Depending on context, consider using container’s “down†or “child†and component’s “up†method to minimize the number of search components
Don’t use
Avoid using document.getElementById()
Avoid using Ext.getCmp()
Avoid usage of hard coded “id†property.
In case it is being used, there must be a strong reason to do so and explicit comments must be specified
Evaluate possibility of using “itemId†config of components instead
Object References
- Make use of object references while accessing an object / property deeply nested inside an object
- Specifically this is extremely important when such properties are getting accessed / used inside a loop
- Similarly, when you loop on array size then keep the size calculated outside the loop
- It is simple – keep computation-heavy code outside the loop
- Make use of object references while handling events
- All the event handler have the component reference being passed as the first parameter of the method. Make use of that in case you need to change anything on the view
In case you do have a need to update some other view / component then specify reference on that component and make use of controller