Recently in ExtJS Category

Add "setLabel" to ExtJS 4 fields...

| | Comments (0)

A trivial override:

Ext.form.field.Base.override({
    setLabel: function (text) {
        if (this.rendered) {
            Ext.get(this.labelEl.id).update(text);
        }
        this.fieldLabel = text;
    }
});

Make ExtJS 4 disabled fields darker

| | Comments (0)

I find the disabled fields in ExtJS 4 (and 3) too light, especially in Safari/Chrome. Just add this to your application’s CSS file to make them darker:

.x-item-disabled {
    color: #888888 !important;
    -moz-opacity: 100;
    opacity: 1;
}

.x-form-item-label .x-item-disabled {
    color: #888888 !important;
    -moz-opacity: 100;
    opacity: 1;
}

ExtJS 3 - How to make a draggable Panel

| | Comments (1)

Just creating an Ext.Panel with ‘draggable’ set to true will give you a panel that you can drag around, but you need to override the ‘onDrag’ and ‘endDrag’ methods to track the position of the panel when it’s being dragged and set it to that position when the drag ends.

 

var panel = new Ext.Panel({
    draggable: {
      insertProxy: false,
      onDrag: function(e) {
        var el = this.proxy.getEl();
        this.x = el.getLeft(true);
        this.y = el.getTop(true);
      },
      endDrag: function(e) {
        this.panel.setPosition(this.x, this.y);
      }
    },
    title: 'Panel',
    width: 400,
    height: 400,
    x: 20,
    y: 20
  });

How to have an image that’s both draggable & resizable:

 

Ext.onReady(function() {
var el = Ext.get('image1');
el.dd = new Ext.dd.DDProxy('image1', 'group');
var r = new Ext.Resizable('image1', {
    preserveRatio: true,
    width: 400,
    height: 300,
    resizeChild: true
  });
});

 

The above assumes you have your image wrapped in a <div> with an id of “image1”, ie:

<div id=”image1”><img src=”images/test1.jpg”/></div>

 

In ExtJS 3.x to listen for double-click events on a GridPanel you attach a listener to the GridPanel like this:

this.on('rowdblclick', function(eventGrid, rowIndex, e) {
  console.log('double click');
}, this);

 

In ExtJS 4.0 you need to listen for events on the GridPanel’s view, via the “viewConfig”:

viewConfig: {
listeners: {
dblclick: function(dataview, index, item, e) { console.log('dblclick'); } } }

 

In my case, I wanted the GridPanel to fire a ‘rowdblclick’ event just like it did in Ext 3.x, so I defined my Ext 4.x GridPanel class like this:

Ext.define('MyGridPanel', {
  extend: 'Ext.grid.GridPanel',
  viewConfig: {
listeners: {
'dblclick': {
fn: function(dataview, index, item, e) {
var gridPanel = this.ownerCt.ownerCt;
gridPanel.fireEvent('rowdblclick', this, index, e);
}
}
}
},
initComponent: function() {
    this.addEvents(
      'rowdblclick'
      );
    this.callParent(arguments);
  }
});

 

The “this.ownerCt.ownerCt” in the handler seems like hackery to me, but for now at least, in PR3, it works.  Anyone have a better solution?

 

UPDATE FOR PR4:

The line “var gridPanel = this.ownerCt.ownerCt;” should be “var gridPanel = this.ownerCt;”

 

ExtJS cursor position in a TextArea or TextField

| | Comments (0)


Say you have a standard ExtJS TextArea with a ‘keyup’ event listener, ie:

var commentsField = new Ext.form.TextArea({
    fieldLabel: 'Comments',
    name: 'Comments',
    enableKeyEvents: true
});

commentsField.on('keyup', function(field, e) {

    // Here's how you get the current cursor position/selection range:

    var s, e;

    if (Ext.isIE) {
        var bookmark = document.selection.createRange().getBookmark();
        var selection = field.el.dom.createTextRange();
        selection.moveToBookmark(bookmark);

        var before = field.el.dom.createTextRange();
        before.collapse(true);
        before.setEndPoint("EndToStart", selection);

        var selLength = selection.text.length;

        s = before.text.length;
        e = s + selLength;

    } else {
        s = field.el.dom.selectionStart;
        e = field.el.dom.selectionEnd;
    }
}, this);



Just in case anyone would like to save the hour or so of Googling it took me to figure this out.

RESTful store example as a pre-configured class

| | Comments (2)

The ExtJS 3.2+ examples include a “RESTful store” which is a very interesting no-code way to get full CRUD behaviour from a GridPanel. Unfortunately the example is not written with a reusable structure - here is the same example, but as a pre-configured class:


Ext.onReady(function() {
            Ext.QuickTips.init();

            var TheGrid = Ext.extend(Ext.grid.GridPanel, {
                        title: 'Users',
                        frame: true,
                        height: 300,
                        width: 500,
                        viewConfig: {
                            forceFit: true
                        },
                        editor: new Ext.ux.grid.RowEditor({
                                    saveText: 'Update'
                                }),


                        onAdd: function(btn, ev) {
                            var u = new this.store.recordType({
                                        first: '',
                                        last: '',
                                        email: ''
                                    });
                            this.editor.stopEditing();
                            this.store.insert(0, u);
                            this.editor.startEditing(0);
                        },


                        onDelete: function() {
                            var rec = this.getSelectionModel().getSelected();
                            if (rec) {
                                this.store.remove(rec);
                            }
                        },


                        initComponent: function() {
                            var proxy = new Ext.data.HttpProxy({
                                        url: 'app.php/users'
                                    });

                            var reader = new Ext.data.JsonReader({
                                        totalProperty: 'total',
                                        successProperty: 'success',
                                        idProperty: 'id',
                                        root: 'data',
                                        messageProperty: 'message' // attribute in server response for user message...
                                    }, [{
                                                name: 'id'
                                            }, {
                                                name: 'email'
                                            }, {
                                                name: 'first',
                                                allowBlank: false
                                            }, {
                                                name: 'last'
                                            }]);

                            var writer = new Ext.data.JsonWriter({
                                        encode: false
                                    });

                            var store = new Ext.data.Store({
                                        restful: true,
                                        proxy: proxy,
                                        reader: reader,
                                        writer: writer
                                    });

                            var config = {
                                store: store,
                                plugins: [this.editor],
                                columns: [{
                                            header: "ID",
                                            width: 40,
                                            sortable: true,
                                            dataIndex: 'id'
                                        }, {
                                            header: "Email",
                                            width: 100,
                                            sortable: true,
                                            dataIndex: 'email',
                                            editor: new Ext.form.TextField({})
                                        }, {
                                            header: "First",
                                            width: 50,
                                            sortable: true,
                                            dataIndex: 'first',
                                            editor: new Ext.form.TextField({})
                                        }, {
                                            header: "Last",
                                            width: 50,
                                            sortable: true,
                                            dataIndex: 'last',
                                            editor: new Ext.form.TextField({})
                                        }],
                                tbar: [{
                                            text: 'Add',
                                            iconCls: 'silk-add',
                                            handler: this.onAdd,
                                            scope: this
                                        }, '-', {
                                            text: 'Delete',
                                            iconCls: 'silk-delete',
                                            handler: this.onDelete,
                                            scope: this
                                        }, '-']
                            };

                            Ext.apply(this, Ext.apply(this.initialConfig, config));
                            TheGrid.superclass.initComponent.apply(this, arguments);

                        },


                        onRender: function() {
                            this.store.load();
                            TheGrid.superclass.onRender.apply(this, arguments);
                        }
                    });
            Ext.reg('my_grid', TheGrid);



            var w = new Ext.Window({
                        modal: true,
                        items: {
                            xtype: 'my_grid',
                            title: 'Panel 1'
                        }
                    });
            w.show();
        });


Using the 'ref' option in ExtJS 3.x

| | Comments (0)

As with so many things in ExtJS, the ‘ref’ option introduced in 3.0 is not very well documented, at least as far as I can tell. Which is unfortunate, because it’s extremely useful, and drastically reduces the need for ids. Here’s an example of how to use it:

Ext.onReady(function() {
            Ext.BLANK_IMAGE_URL = 'ext/resources/images/default/s.gif';
            Ext.QuickTips.init();


            // Define a simple component

            MyComponent = Ext.extend(Ext.form.FormPanel, {
                        frame: true,

                        initComponent: function() {
                            var config = {
                                items: [{
                                            xtype: 'textfield',
                                            fieldLabel: 'Name'
                                        }, {
                                            xtype: 'textfield',
                                            fieldLabel: 'Address'
                                        }],
                                bbar: ['->', {
                                            text: 'Cancel',
                                            minWidth: 100,
                                            ref: '../cancelButton' 
                                        }, {
                                            text: 'Save',
                                            minWidth: 100,
                                            ref: '../saveButton' 
                                        }]
                            };

                            Ext.apply(this, Ext.apply(this.initialConfig, config));
                            MyComponent.superclass.initComponent.apply(this, arguments);

                        }
                    });
            Ext.reg('my_component_xtype', MyComponent);


            // Create a display a window with the panel in it...

            var w = new Ext.Window({
                        modal: true,
                        items: {
                            xtype: 'my_component_xtype',
                            title: 'Panel 1',
                            ref: 'theFormPanel'
                        }
                    });
            w.show();


            // See how we can use the references...

            w.theFormPanel.saveButton.on('click', function() {
                        console.log('Save was clicked');
                    }, this);

            console.log(w.theFormPanel.title);
        });

Enabling event bubbling for all items in a class

| | Comments (0)

There doesn't seem to be direct way in ExtJS to indicate that all items in a class should bubble events. Below is simple workaround - we iterate over all the items in the class in the 'afterRender' event:


Ext.BLANK_IMAGE_URL = 'lib/ext/resources/images/default/s.gif';

Ext.onReady(function() {
        Ext.QuickTips.init();


        FP = Ext.extend(Ext.form.FormPanel, {
                    frame: true,

                    initComponent: function() {
                        var config = {
                            items: [{
                                        xtype: 'textfield',
                                        name: 'First',
                                        fieldLabel: 'First'
                                    }, {
                                        xtype: 'textfield',
                                        name: 'Second',
                                        fieldLabel: 'Second'
                                    }]
                        };

                        Ext.apply(this, Ext.apply(this.initialConfig, config));
                        FP.superclass.initComponent.apply(this, arguments);

                        this.on('change', function(field, newVal, oldVal) {
                                    console.log('form change event on ' + field.name);
                                }, this);
                    },


                    // When the form has been rendered, we step though all the items on 
                    // the form and enable bubbling for each one. In a more complex form
                    // we would need to check the type of each item and enable the right
                    // kind of events, of course.

                    afterRender: function() {
                        FP.superclass.afterRender.apply(this, arguments);
                        Ext.each(this.items.items, function(item) {
                                    item.enableBubble('change');
                                }, this);
                    }
                });


        var fp = new FP();
        var win = new Ext.Window({
                    items: [fp]
                });
        win.show();
    });

Complex objects in classes (Ext3 & Ext4 examples)

| | Comments (0)


When using Ext.extend (Ext3) or Ext.define (Ext4) to create your own classes, it's critical to understand that complex objects defined outside of a function definition are added to the prototype of the extended class, and as such are shared across all instances of the class. This sharing is not the case with simple attributes.

The solution is to define complex objects inside the "initComponent" function, referencing them via "this".

Ext4 Example:

Ext.onReady(function() {
  Ext.QuickTips.init();

  // This class definition is broken for most uses - the 'obj' complex object is
  // created when the class is defined, and as such is shared across all instances
  // of the class! Confusingly, 'simple' class attributes are /not/ shared.

  Ext.define('BrokenClass', {
    extend: 'Ext.Panel',
    obj: {
      colour: 'red'
    },
    simple: 'one', // this is not shared

    initComponent: function() {
      this.callParent();
    }
  });


  // This class definition is not broken - the 'obj' complex object is created when an
  // instance of the class is created, and thus is unique to each instance.

  Ext.define('WorkingClass', {
    extend: 'Ext.Panel',
    initComponent: function() {
      this.obj = {
        colour: 'red'
      };
      WorkingClass.superclass.initComponent.apply(this, arguments);
    }
  });


  // Note that b1 and b2 share the value of 'obj', but do NOT share the value
  // of 'simple'

  var b1 = Ext.create('BrokenClass');
  var b2 = Ext.create('BrokenClass');

  b2.obj.colour = 'blue';
  b2.simple = 'two';

  console.log(b1.obj.colour, b2.obj.colour, b1.simple, b2.simple);


  // Note that w1 and w2 each have their own values for 'obj'

  var w1 = Ext.create('WorkingClass');
  var w2 = Ext.create('WorkingClass');

  w1.obj.colour = 'blue';

  console.log(w1.obj.colour, w2.obj.colour);
});





Ext3 Example:

Ext.BLANK_IMAGE_URL = 'lib/ext/resources/images/default/s.gif';

Ext.onReady(function() {
        Ext.QuickTips.init();

    // This class definition is broken for most uses - the 'obj' complex object is 
    // created when the class is defined, and as such is shared across all instances
    // of the class! Confusingly, 'simple' class attributes are /not/ shared.

        BrokenClass = Ext.extend(Ext.Panel, {
                    obj: {
                        colour: 'red'
                    },
                    simple: 'one', // this is not shared

                    initComponent: function() {
                        BrokenClass.superclass.initComponent.apply(this, arguments);
                    }
                });


    // This class definition is not broken - the 'obj' complex object is created when an 
    // instance of the class is created, and thus is unique to each instance.

        WorkingClass = Ext.extend(Ext.Panel, {
                    initComponent: function() {
                        this.obj = {
                            colour: 'red'
                        };
                        WorkingClass.superclass.initComponent.apply(this, arguments);
                    }
                });



    // Note that b1 and b2 share the value of 'obj', but do NOT share the value 
    // of 'simple'

        var b1 = new BrokenClass();
        var b2 = new BrokenClass();

        b2.obj.colour = 'blue';
        b2.simple = 'two';

        console.log(b1.obj.colour, b2.obj.colour, b1.simple, b2.simple);


        // Note that w1 and w2 each have their own values for 'obj'

        var w1 = new WorkingClass();
        var w2 = new WorkingClass();

        w1.obj.colour = 'blue';

        console.log(w1.obj.colour, w2.obj.colour);
    });

About this Archive

This page is a archive of recent entries in the ExtJS category.

Drupal is the previous category.

Other is the next category.

Find recent content on the main index or look in the archives to find all content.

Pages

Powered by Movable Type 4.34-en