Ext JS with PHP: How to Add Children to Async Tree Nodes

After reading Ext JS with PHP: How to Create Nodes for a TreePanel, some readers have asked how the aproach discussed in the article can be extended to add children to any async node, as shown in the following screenshot:

extjs-tree-nodes-2

In our Ext JS TreePanel, expanding any parent node (My Project, Datasources and Reports) will generate an http request for the node’s children.  What we need to do then is monitor the request parameters, determine which parent node should be populated, and generate the child nodes.  Let’s modify our original code so we can accomplish this.

A PHP model for Ext JS tree nodes

First, remember that we’re using the following PHP classes to model the Ext JS tree nodes:

class TreeNode {
    
    public $text = "";
    public $id = "";
    public $iconCls = "";
    public $leaf = true;
    public $draggable = false;
    public $href = "#";
    public $hrefTarget = "";

    function  __construct($id,$text,$iconCls,$leaf,$draggable,
            $href,$hrefTarget) {
    
        $this->id = $id;
        $this->text = $text;
        $this->iconCls = $iconCls;
        $this->leaf = $leaf;
        $this->draggable = $draggable;
        $this->href = $href;
        $this->hrefTarget = $hrefTarget;    
    }    
}

class TreeNodes {
    
    protected $nodes = array();
    
    function add($id,$text,$iconCls,$leaf,$draggable,
        $href,$hrefTarget) {
    
        $n = new TreeNode($id,$text,$iconCls,$leaf,
                $draggable,$href,$hrefTarget);
        
        $this->nodes[] = $n;
    }
    
    function toJson() {
        return json_encode($this->nodes);
    }
}

Creating children for Ext JS async tree nodes

We now need to capture the parent node that is making the request:

$requestedNode = "";

if (isset($_REQUEST["node"])) {
    $requestedNode = $_REQUEST["node"];
}

With the parent node captured, we can build its child nodes, and send them to the Ext JS client:

$treeNodes = new TreeNodes();

if ('node-root' == $requestedNode) {
    $treeNodes->add("node-datasources","Datasources","",false,false,"","");
    $treeNodes->add("node-reports","Reports","",false,false,"","");
} else if ('node-datasources' == $requestedNode) {
    $treeNodes->add("employees-system-node","Employee Management System","datasource",true,false,"","");
    $treeNodes->add("customers-system-node","Customer Management System","datasource",true,false,"","");
    $treeNodes->add("order-system-node","Order Processing System","datasource",true,false,"","");
} else if ('node-reports' == $requestedNode) {
    $treeNodes->add("time-report-node","Time and Attendance","report",true,false,"","");
    $treeNodes->add("orders-by-quarter-report-node","Orders By Quarter","report",true,false,"","");
    $treeNodes->add("customers-trends-report-node","Customer Trends","report",true,false,"","");
}

echo $treeNodes->toJson();

And this is the TreePanel definition:

var tree = new Ext.tree.TreePanel({
    renderTo: Ext.getBody(),
    title: 'Reporting Project',
    width: 250,
    height: 250,
    userArrows: true,
    animate: true,
    autoScroll: true,
    dataUrl: 'tree-nodes-2.php',
    root: {
        nodeType: 'async',
        text: 'My Project',
        id:'node-root'
    },
    listeners: {
        render: function() {
            this.getRootNode().expand();
        }
    }
})

This is, my friends, all it takes to add children to Ext JS async tree nodes using PHP.  Want to share your preferred approach?

Downloads

Grab the code for this article from my downloads page.

Want to learn more?

Ext-JS-Cookbook Check out my Ext JS 3.0 Cookbook.  It contains more than a hundred step-by-step recipes that explain useful techniques you can use to build great Ext JS applications.

E-mail   Permalink    Comments(0)   Trackback

Tags: , ,

Using the Ext Scheduler, Part 2

This is another article where we will explore the Ext Scheduler while we use it to build a hypothetical conference room reservations interface.  In Using the Ext Scheduler, Part 1, we set out to to build a scheduler that displays the reservations that exist for a number of conference rooms.  This time the goal is to add the the ability to create, edit and remove reservations.

ext-scheduler

We will allow for creation and edition of reservations by using the scheduler’s EventEditor plugin.  For deletions, we will use a simple context menu.  Let’s see how it is done.

Editing events in the Ext Scheduler

The first change we are going to make in order to support event edition is use a specialized version of the scheduler - the Sch.EditorSchedulerPanel class - as the data type for the scheduler. (In Using the Ext Scheduler, Part 1 we employed the Sch.SchedulerPanel class.)

ConfRooms.sch = new Sch.EditorSchedulerPanel({

// Configuration...

});

The scheduler’s event editor is a plugin (Sch.plugins.EventEditor class) that defines a number of UI elements that display next to the event being edited.  This is how our reservation editor will look:

ext-scheduler-event-editor

In the editor, a built-in header region contains the input fields for the start date and duration of the event.  A separate region contains fields for any other event properties that we might want to include in the editor.  This region is configurable through the fieldsPanelConfig option of the EventEditor class.  Let’s write the code that defines our editor:

plugins: [
    this.editor = new Sch.plugins.EventEditor({
        height: 180,
        width: 270,
        buttonAlign: 'center',
        saveHandler: ConfRooms.onSave,
        saveHandlerScope: this,
        fieldsPanelConfig: {
            layout: 'form',
            border: false,
            cls: 'editorpanel',
            labelAlign: 'top',
            items: [
                descriptionField = new Ext.form.TextArea({
                    name: 'Description',
                    fieldLabel: 'Description',
                    anchor: '100%'
                })
            ]
        },
        listeners: {
            expand: function() {
                descriptionField.focus(true);
            }
        }
    })
]

Note how we use the fieldsPanelConfig.items property to add a text area so our users can change the description of the edited event, in this case a conference room reservation.

Another important configuration option of the event editor is saveHandler.  This option specifies the function that will take care of saving the changes made to the reservation.  This is the implementation of our saveHandler:

ConfRooms.onSave = function(formPanel, newStart, newEnd, record) {
     record.beginEdit();
     formPanel.getForm().updateRecord(record);
     record.set('StartDate', newStart);
     record.set('EndDate', newEnd);
     record.endEdit();

     if (!record.get('Id')) {
         this.grid.eventStore.add([event]);
     }
     formPanel.collapse();
}

Our handler first updates the reservation’s description through a call to the underlying form’s updateRecord() function, it then updates the start and end dates, and finally, it inspects the record’s id in order to determine if it is a new or an existing reservation.

Creating events in the Ext Scheduler

As depicted below, we will allow our users to create a reservation with a drag and drop gesture over the desired time period:

ext-scheduler-new-event

While the editor’s UI is automatically shown upon double-cliking on an existing reservation, we need to take care of showing the UI when the user creates a new reservation. This is why we will add a handler for the scheduler’s dragcreateend event:

dragcreateend: {
 fn: function(p, data, e) {
     var reservation = new ConfRooms.reservationsStore.recordType({
         Id: ConfRooms.nextId(),
         Description: 'Enter a description for this event',
         ReservedTo: 'Jorge Ramon',
         ResourceId: data.record.get('Id'),
         StartDate: data.startDate,
         EndDate: data.endDate
     });

     ConfRooms.reservationsStore.add(reservation);
     this.editor.show(reservation);
 },
 scope: this
}

The handler for dragcreateend first creates a new reservation record, capturing the start and end dates passed by the scheduler via the data parameter.  It then adds the new record to the reservations store, and displays the editor’s user interface by calling editor.show().

It really doesn’t take much effort to implement event edition in the Ext Scheduler.  Let’s now take a look at deleting events.

Deleting events in the Ext Scheduler

We already gave the users of our conference room reservation system the ability to create and edit reservations, but we are missing an easy way to delete reservations.  To accomplish this we will attach a “Delete” context menu to each reservation displayed on the scheduler.  Here’s a depiction of the menu:

ext-scheduler-delete-menu

We can attach this menu to the each reservation by taking advantage of the eventcontextmenu configuration option of the scheduler:

eventcontextmenu: {
 fn: function(g, rec, e) {
     e.stopEvent();
     if (!this.gCtx) {
         this.gCtx = new Ext.menu.Menu({
             items: [
                {
                    id: 'context-delete',
                    text: 'Delete event',
                    iconCls: 'icon-delete'
                }
            ]
         });

         this.gCtx.on('itemclick', function(item, e) {
             switch (item.id) {
                 case 'context-delete':
                     ConfRooms.sch.eventStore.remove(this.gCtx.rec);                                             
                     break;

                 default:
                     throw item.id + ' is not a valid menu action';
                     break;
             }
         }, this);
     }
     this.gCtx.rec = rec;
     this.gCtx.showAt(e.getXY());
 }

The interesting part of the context menu definition is the itemclick handler, which is where we remove the reservation from its data store.

Conclusion

This brings to completion the features we set out to work on in this article, and we now have a simple conference room reservation system based on the Ext Scheduler.

I encourage you to try and experiment with the source code for this article, as well as check out the scheduler’s examples and support materials.

Downloads

Grab the code for the sample from my downloads page.  You can obtain the Ext Scheduler at http://www.ext-scheduler.com.

E-mail   Permalink    Comments(0)   Trackback

Tags: ,