Results 1 to 2 of 2

Thread: ColumnTree with radio group

  1. #1
    Sencha User
    Join Date
    Aug 2009
    Location
    Austin, TX
    Posts
    100

    Default ColumnTree with radio group

    Hi all-

    I am trying to customize the ColumnTree example to have the ability to add a radio group to each leaf node. To this point I have gotten to where I can display any number of radio buttons in each node's group by passing in an array of Strings as the values of each radio. The first time I click on any radio in the group, it selects that radio. Subsequent clicks do not change the radio group at all.

    <see attached screenshot of columntree>

    The odd thing is though, if I set a break point in the "onClick" event in Firebug, when I click an unchecked radio in the group, it now shows as checked and the other(s) unchecked. If I remove the break point the radios do not toggle anymore. How does setting a break point change the way it functions?

    Maybe there's something to the onRadioChange that I attempted to update from the onCheckChange from TreeNodeUI.js.

    I believe the necessary code is below.

    ColumnNodeRadioUI.js
    Code:
    /*!
     * Ext JS Library 3.0.3
     * Copyright(c) 2006-2009 Ext JS, LLC
     * [email protected]
     * http://www.extjs.com/license
     */
    Ext.ns('Ext.ux.tree');
    
    /**
     * @class Ext.ux.tree.ColumnTree
     * @extends Ext.tree.TreePanel
     * 
     * @xtype columntree
     */
    Ext.ux.tree.ColumnTree = Ext.extend(Ext.tree.TreePanel, {
        lines : false,
        borderWidth : Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
        cls : 'x-column-tree',
        
        onRender : function(){
            Ext.tree.ColumnTree.superclass.onRender.apply(this, arguments);
            this.headers = this.header.createChild({cls:'x-tree-headers'});
    
            var cols = this.columns, c;
            var totalWidth = 0;
            var scrollOffset = 19; // similar to Ext.grid.GridView default
    
            for(var i = 0, len = cols.length; i < len; i++){
                 c = cols[i];
                 totalWidth += c.width;
                 this.headers.createChild({
                     cls:'x-tree-hd ' + (c.cls?c.cls+'-hd':''),
                     cn: {
                         cls:'x-tree-hd-text',
                         html: c.header
                     },
                     style:'width:'+(c.width-this.borderWidth)+'px;'
                 });
            }
            this.headers.createChild({cls:'x-clear'});
            // prevent floats from wrapping when clipped
            this.headers.setWidth(totalWidth+scrollOffset);
            this.innerCt.setWidth(totalWidth);
        }
    });
    
    Ext.reg('columntree', Ext.ux.tree.ColumnTree);
    
    //backwards compat
    Ext.tree.ColumnTree = Ext.ux.tree.ColumnTree;
    
    
    /**
     * @class Ext.ux.tree.ColumnNodeUI
     * @extends Ext.tree.TreeNodeUI
     */
    Ext.ux.tree.ColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
        focus: Ext.emptyFn, // prevent odd scrolling behavior
    
        // private
        onDisableChange : function(node, state){
            this.disabled = state;
            if (this.radioObjs) {
                for (var i = 0; i < this.radioObjs.length; i++) {
                    this.radioObjs[i].disabled = state;
                }
            }        
            if(state){
                this.addClass("x-tree-node-disabled");
            }else{
                this.removeClass("x-tree-node-disabled");
            } 
        },
    
        // private
        onClick : function(e){
            if(this.dropping){
                e.stopEvent();
                return;
            }
            if(this.fireEvent("beforeclick", this.node, e) !== false){
                var a = e.getTarget('a');
                if(!this.disabled && this.node.attributes.href && a){
                    this.fireEvent("click", this.node, e);
                    return;
                }else if(a && e.ctrlKey){
                    e.stopEvent();
                }
                e.preventDefault();
                if(this.disabled){
                    return;
                }
    
                if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
                    this.node.toggle();
                }
    
                this.fireEvent("click", this.node, e);
            }else{
                e.stopEvent();
            }
        },
    
        // private
        onRadioChange : function(){
            for (var i = 0; i < this.radioObjs.length; i++) {
                var checked = this.radioObjs[i].checked;
                // fix for IE6
                this.radioObjs[i].defaultChecked = checked;
                this.node.attributes.checked = checked;            // TODO ? Not sure what this line is for
            }
            this.fireEvent('radiochange', this.node, checked);
        },
    
        toggleCheck : function(value){
            var cb = this.checkbox;
            if(cb){
                cb.checked = (value === undefined ? !cb.checked : value);
                this.onRadioChange();
            }
        },
    
        renderElements : function(n, a, targetNode, bulkRender){
            this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
    
            var tree = n.getOwnerTree();
            var cols = tree.columns;
            var bw = tree.borderWidth;
            var c = cols[0];
            var radio = Ext.isDefined(a.radioValues);
            var numRadios = 0;
            
            var radioHTML = '';
            // If the configuration calls for radio buttons, then construct the HTML here for each radio
            if (radio){
                var radioVals = a.radioValues;
                numRadios = radioVals.length;
                for (var i = 0; i < numRadios; i++) {
                    radioHTML += '<input class="x-tree-node-cb" name="'+n.id+'radio" type="radio" value="' + radioVals[i] + '" />';
                }
            }
    
            var buf = [
                 '<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf ', a.cls,'">',
                    '<div class="x-tree-col" style="width:',c.width-bw,'px;">',
                        '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
                        '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
                        '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
                        radioHTML,
                        '<a hidefocus="on" class="x-tree-node-anchor" href="',a.href ? a.href : "#",'" tabIndex="1" ',
                        a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
                        '<span unselectable="on">', n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</span></a>",
                    "</div>"];
             for(var i = 1, len = cols.length; i < len; i++){
                 c = cols[i];
    
                 buf.push('<div class="x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
                            '<div class="x-tree-col-text">',(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</div>",
                          "</div>");
             }
             buf.push(
                '<div class="x-clear"></div></div>',
                '<ul class="x-tree-node-ct" style="display:none;"></ul>',
                "</li>");
    
            if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
                this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
                                    n.nextSibling.ui.getEl(), buf.join(""));
            }else{
                this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
            }
    
            this.elNode = this.wrap.childNodes[0];
            this.ctNode = this.wrap.childNodes[1];
            var cs = this.elNode.firstChild.childNodes;
            this.indentNode = cs[0];
            this.ecNode = cs[1];
            this.iconNode = cs[2];
            var index = 3;
            if (radio) {
                this.radioObjs = new Array();
                for (var i = 0; i < numRadios; i++) {
                    this.radioObjs[i] = cs[index++];
                }
            }
            this.anchor = cs[index];
            this.textNode = cs[index].firstChild;
        }
    });
    
    //backwards compat
    Ext.tree.ColumnNodeUI = Ext.ux.tree.ColumnNodeUI;
    column-tree.js
    Code:
    /*!
     * Ext JS Library 3.0.3
     * Copyright(c) 2006-2009 Ext JS, LLC
     * [email protected]
     * http://www.extjs.com/license
     */
    function CommentsLinkCell(value, metaData, record, rowIndex, colIndex, store) {
        if (value != null)
            return "<a href='#' style='text-decoration:underline;color:blue' onClick=displayComments(\"" + value + "\")>Add Comments</a>";
        else
            return '';
    }
    
    function displayComments(text) {
        var win = new Ext.Window({
            layout:'fit',
            title: 'Add Comments',
            width:400,
            height:250,
            modal: true,
            plain: true,
    
            items: new Ext.Panel({
                deferredRender:false,
                border:false,
                layout:'border',
                items:[{
                    xtype:'textarea',
                    region:'center',
                    id:'comments',
                    fieldLabel:'Comments',
                    height:'auto',
                    width:'auto',
                    value:text,
                    anchor:'98%'
                }]
            }),
    
            buttons: [{
                text:'Submit',
                disabled:true
            },{
                text: 'Close',
                handler: function(){
                    win.hide();
                }
            }]
        });
        win.show(this);
    }
    
    Ext.onReady(function(){
        var tree = new Ext.ux.tree.ColumnTree({
            width: 550,
            height: 200,
            rootVisible:false,
            autoScroll:true,
            title: 'Example Tasks',
            renderTo: Ext.getBody(),
    
            columns:[{
                header:'Task',
                width:330,
                dataIndex:'task'
            },{
                header:'Comments',
                width:100,
                dataIndex:'comments',
                renderer: CommentsLinkCell
            },{
                header:'Assigned To',
                width:100,
                dataIndex:'user'
            }],
    
            loader: new Ext.tree.TreeLoader({
                dataUrl:'column-data.json',
                uiProviders:{
                    'col': Ext.ux.tree.ColumnNodeUI
                }
            }),
    
            root: new Ext.tree.AsyncTreeNode({
                text:'Tasks',
                children: [{
                    task:'NOTE',
                    comments:null,
                    user:'',
                    uiProvider:'col',
                    cls:'master-task',
                    iconCls:'task-folder',
                    expanded: true,
                    children:[{
                        task:'Document is missing',
                        comments:null,
                        user:'',
                        uiProvider:'col',
                        iconCls:'task-folder',
                        expanded: true,
                        children:[{
                            task:'Document is missing',
                            comments:'Test',
                            user:'Field',
                            uiProvider:'col',
                            leaf:true,
                            iconCls:'task',
                            radio:true,                        // true to display a radio button group
                            radioValues:['Yes','No'],        // Values for radio buttons...implies number of buttons in group
                            expanded: true
                        }]
                    }]
                },{
                    task:'PHOTO ID',
                    comments:null,
                    user:'',
                    uiProvider:'col',
                    cls:'master-task',
                    iconCls:'task-folder',
                    children:[{
                        task:'Terms do not match system',
                        comments:null,
                        user:'',
                        uiProvider:'col',
                        iconCls:'task-folder',
                        expanded: true,
                        children:[{
                            task:'Address is incorrect',
                            comments:'',
                            user:'Paralender',
                            uiProvider:'col',
                            leaf:true,
                            iconCls:'task',
                            radio:true,                    // true to display a radio button group
                            radioValues:['Yes','No'],    // Values for radio buttons...implies number of buttons in group
                            expanded: true
                        },{
                            task:'ID is expired',
                            comments:'ID shows expired date.',
                            user:'Paralender',
                            uiProvider:'col',
                            leaf:true,
                            iconCls:'task',
                            radioValues:['Yes','No'],    // Values for radio buttons...implies existence of radio group and number of buttons in group
                            expanded: true
                        }]
                    }]
                }]
            })
        });
    });
    Attached Images Attached Images

  2. #2
    Sencha User
    Join Date
    Aug 2009
    Location
    Austin, TX
    Posts
    100

    Default

    I will also want to add a header above the leaf node with the radio group. Since there can be multiple leaf nodes under one folder (unlike the screenshot) I guess the header will need to be another leaf node? I want to put something above each radio to denote what they are for such as a "Y" and "N" above them for "Yes" and "No" options. Any pointers on how to ensure those headers line up with each radio would be greatly appreciated.

    If I'll need to tackle that in another thread, that is fine. Right now functionality is more important to me than look-and-feel as that can always be tweaked.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •