ExtJs 3.4 – Tips and tricks

Introduction

This post is mostly a whole bunch of information I have gathered to using ExtJs 3.4 grouped by different subjects.

I hope any one stuck with Extjs 3.4 to have use for it.

Errors and possible solutions

Writing code and debugging ExtJs can sometimes be a pain because errors trown by browsers are not always clear. Like with most software, not all errors shown point directly to the actual problem. Unforntunately because javascript is very flexible, it can go wrong on many levels.

The following list gives you a guide in which errors indicate to which problems.

this.addEvents is not a function:’statesave’
Check if you use new for all of your created Ext components.

‘events’ is null or not an object
Check comma’s in items arrays

‘minWidth’ is null or not an object
Check comma’s in buttons arrays.

Expected identifier, string or number
Check comma’s inside Ext element config objects or/and arrays.

Comp is undefined
Check for non existing or empty references in an items list.

‘id’ is null or not an object
Check comma’s in ColumnModel arrays.

Unterminated string constant
If it occurs in Internet Explorer it is likely caused by disabling a form prior uploading a file. This somehow causes internet explorer to not send any form information when it is submitted.

TypeError: this.ds is undefined
Stores is not defined for a grid(panel)

Unable to get value of the property ‘0’: object is null or undefined
Check comma’s in field array of stores.

TypeError: this.config[col] is undefinedvar width = this.config[col].width;
Column model with autoexpand not pointing to a valid column. Must point to an id that exists within the column model.

TypeError: c is undefined
Calling add() on a panel/component with an empty or otherwhise faulty reference

Debugging events

Blog about logging all events. https://coderwall.com/p/jnqupq

Store query on exact value

Store ‘fix’ modifiedRecords()

ExtJS store by default does NOT remove records from modified records on remove or load.
To make this happen use pruneModifiedRecords: true to do this

Create new record for store

Find row index from record

Find data index from columnIndex and record from rowIndex

Using filter with combobox

Apply following config options on combo to make it work

Grid rendereres


Set scope of renderer to current object

Grid cellclick with image or other elements in renderer

When rendering images or other deep elements within a cell the cellclick events do not longer work correctly. To fix this increase the GridViews depth search paramters. This works on any type of grid view.

Grid using drag an drop in grids

define following grid config options

Create drop target class after render

Override notifyOver on this dropTarget instance to see if may be dropped Notice: using ‘dd.getDragData(e)’ causes the selections in the selectionModel to be changed

Override notifyDrop on this dropTarget instance to do an action when dropped

Prompt for question

When you want input from the user on a question. Questions like: “sure you want to delete this?”, “Sure you want to go on and lose your unsaved data” etc.
Use the here under described function
Note: Although the buttons can be localized the answer inside the function doesn’t change. Look up the function to see more button configurations if needed.

Checkbox column in grid

Toggle selection

Renderer

Grouping grid The column you want to group with must be included within the columnModel. Even if it’s hidden, it MUST be included.

Use CSS background class to an image

Replacing or reseting upload field

Because of security reasons an upload field cannot be set or reset.
The only way to do so, is to replace the whole field.

See the example below:

Show / hide loadmask

When you are loading or saving something inside your interface, you don’t want the user to change things that might get updated the next second or will not be saved because the actual data is already send to the server. Additionally you would like show the user a vissual indication something is going on.

The following functions add a loadmask to a component to achieve this. The inner workings have been proven to fix problems that occur when this function is called before the actual component is rendered. And even shows the loadMask in the event that rendering completes before loading does.

Managing buttons within a control interface

It sounds trivial, but have you ever found yourself clicking on a button at the bottom of an administrative panel to delete an item while nothing was selected inside a grid or list, presenting you with a ‘nice’ exception.

Why does this happen? The answer is probably: that the most forward way to make button states work, is to manually disable buttons for different actions.

Note: All code are orginall written in Javascript for ExtJs 3.4, but if you can read it are easily transferable to other programming languages.

Consider the following case.

  • You have a grid with items that can be deleted and edited.
  • You can always add something.
  • When you delete something, nothing is selected afterward. So edit and delete should be disabled.

Now there are multiple cases this will break when you manage button states with every action.

  • You add another button, move for example.
    You have to add the disable to the end of edit and delete function.
  • Items get states where they can’t be either deleted or edited.
    The logic of this will be scattered.
  • An item can be deselected by a refresh called from numerous functions.
    Again scattering logic and leaving room for errors.

You get the idea.

Interfaces like this have lot’s of states ending in an even larger list of actions that a possible. So what IS a good way to do this? In my personal opinion it’s best to fit all state information into ONE function.

Why?

  • Because you want the logic to be in one place.
  • You can call this function as often you want, so if you are unsure about states. Call it.
  • When it is done, it is guaranteed to be valid because it doesn’t care which function just got executed.
  • When you add a new state or button you only have to add a little logic to this function and don’t have to bother to check all the other places the state could change in a way unintended.

Last consideration

Yes, it creates some overhead. It will run checks that ‘could’ be unnecessary because part of the buttons only change ‘sometimes’.

That are a lot of ifs. Furthermore checking for states is not that expensive. That is unless you need to loop a whole lot of items to find out if something is true. Which would be a good thing to cache or split off so you only check it when necessary.

You could consider making logical groups that you pass as parameters for things to check during the manageButtons call. But I have not experimented with that yet.

Feel free to leave comments about your own findings on the subject.