1. #1
    Sencha User
    Join Date
    Nov 2014
    Posts
    27
    Vote Rating
    0
    Answers
    1
    JackJohnsonX is on a distinguished road

      0  

    Default Unanswered: Ext.ux.TreeCombo textfield change event

    I am using the custom "treecombo" plugin extensively across my app as inline grid editors. I wanted to know if typeAhead is possible using this custom component? Despite the name, it is in fact NOT a combobox, otherwise I could just add the typeAhead:true config. Below is the source for the treecombo

    Code:
     /*
        Tree combo
        Use with 'Ext.data.TreeStore'
        
        
        If store root note has 'checked' property tree combo becomes multiselect combo (tree store must have records with 'checked' property)
        
        
        Has event 'itemclick' that can be used to capture click
        
        
        Options:
        selectChildren - if set true and if store isn't multiselect, clicking on an non-leaf node selects all it's children
        canSelectFolders - if set true and store isn't multiselect clicking on a folder selects that folder also as a value
        
        
        Use:
        
        
        single leaf node selector:
        selectChildren: false
        canSelectFolders: false
        - this will select only leaf nodes and will not allow selecting non-leaf nodes
        
        
        single node selector (can select leaf and non-leaf nodes)
        selectChildren: false
        canSelectFolders: true
        - this will select single value either leaf or non-leaf
        
        
        children selector:
        selectChildren: true
        canSelectFolders: true
        - clicking on a node will select it's children and node, clicking on a leaf node will select only that node
        
        
        This config:
        selectChildren: true
        canSelectFolders: false
        - is invalid, you cannot select children without node
        
        
        */
        Ext.define('Ext.ux.TreeCombo',
        {
            extend: 'Ext.form.field.Picker',
            alias: 'widget.treecombo',
            tree: false,
            constructor: function(config)
            {
                this.addEvents(
                {
                    "itemclick" : true
                });
        
        
                this.listeners = config.listeners;
                this.callParent(arguments);
            },
            records: [],
            recursiveRecords: [],
            ids: [],
            selectChildren: true,
            canSelectFolders: true,
            multiselect: false,
            displayField: 'text',
            valueField: 'id',
            treeWidth: 300,
            matchFieldWidth: false,
            treeHeight: 400,
            masN: 0,
            recursivePush: function(node, setIds)
            {
                var    me = this;
        
        
                me.addRecRecord(node);
                if(setIds) me.addIds(node);
                
                node.eachChild(function(nodesingle)
                {
                    if(nodesingle.hasChildNodes() == true)
                    {
                        me.recursivePush(nodesingle, setIds);
                    }
                    else
                    {
                        me.addRecRecord(nodesingle);
                        if(setIds) me.addIds(nodesingle);
                    }
                });
            },
            recursiveUnPush: function(node)
            {
                var    me = this;
                me.removeIds(node);
                
                node.eachChild(function(nodesingle)
                {
                    if(nodesingle.hasChildNodes() == true)
                    {
                        me.recursiveUnPush(nodesingle);
                    }
                    else me.removeIds(nodesingle);
                });
            },
            addRecRecord: function(record)
            {
                var    me = this;
        
        
                for(var i=0,j=me.recursiveRecords.length;i<j;i++)
                {
                    var item = me.recursiveRecords[i];
                    if(item)
                    {
                        if(item.getId() == record.getId()) return;
                    }
                }
                me.recursiveRecords.push(record);
            },
            afterLoadSetValue: false,
            setValue: function(valueInit)
            {
                if(typeof valueInit == 'undefined') return;
                
                var    me = this,
                    tree = this.tree,
                    values = (valueInit == '') ? [] : valueInit.split(','),
                    valueFin = [];
                    
                inputEl = me.inputEl;
        
        
                if(tree.store.isLoading())
                {
                    me.afterLoadSetValue = valueInit;
                }
        
        
                if(inputEl && me.emptyText && !Ext.isEmpty(values))
                {
                    inputEl.removeCls(me.emptyCls);
                }
        
        
                if(tree == false) return false;
                
                var node = tree.getRootNode();
                if(node == null) return false;
                
                me.recursiveRecords = [];
                me.recursivePush(node, false);
                
                me.records = [];
                Ext.each(me.recursiveRecords, function(record)
                {
                    var    id = record.get(me.valueField),
                        index = values.indexOf(''+id);
                
                    if(me.multiselect == true) record.set('checked', false);
                    
                    if(index != -1)
                    {
                        valueFin.push(record.get(me.displayField));
                        if(me.multiselect == true) record.set('checked', true);
                        me.addRecord(record);
                    }
                });
        
        
                me.value = valueInit;
                me.setRawValue(valueFin.join(', '));
                
                me.checkChange();
                me.applyEmptyText();
                return me;
            },
            getValue: function() 
            {
                return this.value;
            },
            getSubmitValue: function()
            {
                return this.value;
            },
            checkParentNodes: function(node)
            {
                if(node == null) return;
                
                var    me = this,
                    checkedAll = true;
        
        
                node.eachChild(function(nodesingle)
                {
                    var    id = nodesingle.getId(),
                        index = me.ids.indexOf(''+id);
                        
                    if(index == -1) checkedAll = false;
                });
                
                if(checkedAll == true)
                {
                    me.addIds(node);
                    me.checkParentNodes(node.parentNode);
                }
                else
                {
                    me.removeIds(node);
                    me.checkParentNodes(node.parentNode);
                }
            },
            initComponent: function() 
            {
                var    me = this;
                
                me.tree = Ext.create('Ext.tree.Panel',
                {
                    alias: 'widget.assetstree',
                    hidden: true,
                    minHeight: 300,
                    rootVisible: (typeof me.rootVisible != 'undefined') ? me.rootVisible : true,
                    floating: true,
                    useArrows: true,
                    width: me.treeWidth,
                    autoScroll: true,
                    height: me.treeHeight,
                    store: me.store,
                    listeners:
                    {
                        load: function(store, records)
                        {
                            if(me.afterLoadSetValue != false)
                            {
                                me.setValue(me.afterLoadSetValue);
                            }
                        },
                        itemclick:  function(view, record, item, index, e, eOpts)
                        {
                            me.itemTreeClick(view, record, item, index, e, eOpts, me)
                        }
                    }
                });
                
                if(me.tree.getRootNode().get('checked') != null) me.multiselect = true;
                
                this.createPicker = function()
                {
                    var    me = this;
                    return me.tree;
                };
                
                this.callParent(arguments);
            },
            addIds: function(record)
            {
                var    me = this;
                
                if(me.ids.indexOf(''+record.getId()) == -1) me.ids.push(''+record.get(me.valueField));
            },
            removeIds: function(record)
            {
                var    me = this,
                    index = me.ids.indexOf(''+record.getId());
                    
                if(index != -1)
                {
                    me.ids.splice(index, 1);
                }
            },
            addRecord: function(record)
            {
                var    me = this;
        
        
                for(var i=0,j=me.records.length;i<j;i++)
                {
                    var item = me.records[i];
                    if(item)
                    {
                        if(item.getId() == record.getId()) return;
                    }
                }
                me.records.push(record);
            },
            removeRecord: function(record)
            {
                var    me = this;
        
        
                for(var i=0,j=me.records.length;i<j;i++)
                {
                    var item = me.records[i];
                    if(item && item.getId() == record.getId()) delete(me.records[i]);
                }
            },
            itemTreeClick: function(view, record, item, index, e, eOpts, treeCombo)
            {
                var    me = treeCombo,
                    checked = !record.get('checked');//it is still not checked if will be checked in this event
                
                if(me.multiselect == true) record.set('checked', checked);//check record
                
                var node = me.tree.getRootNode().findChild(me.valueField, record.get(me.valueField), true);
                if(node == null) 
                {
                    if(me.tree.getRootNode().get(me.valueField) == record.get(me.valueField)) node = me.tree.getRootNode();
                    else return false;
                }
                
                if(me.multiselect == false) me.ids = [];
                
                //if it can't select folders and it is a folder check existing values and return false
                if(me.canSelectFolders == false && record.get('leaf') == false)
                {
                    me.setRecordsValue(view, record, item, index, e, eOpts, treeCombo);
                    return false;
                }
                
                //if record is leaf
                if(record.get('leaf') == true) 
                {
                    if(checked == true)
                    {
                        me.addIds(record);
                    }
                    else
                    {
                        me.removeIds(record);
                    }
                }
                else //it's a directory
                {            
                    me.recursiveRecords = [];
                    if(checked == true)
                    {
                        if(me.multiselect == false)
                        {
                            if(me.canSelectFolders == true) me.addIds(record); 
                        }
                        else
                        {
                            if(me.canSelectFolders == true)
                            {
                                me.recursivePush(node, true);
                            }
                        }
                    }
                    else
                    {
                        if(me.multiselect == false)
                        {
                            if(me.canSelectFolders == true) me.recursiveUnPush(node);
                            else me.removeIds(record);
                        }
                        else me.recursiveUnPush(node);
                    }
                }
                
                //this will check every parent node that has his all children selected
                if(me.canSelectFolders == true && me.multiselect == true) me.checkParentNodes(node.parentNode);
                
                me.setRecordsValue(view, record, item, index, e, eOpts, treeCombo);
            },
            fixIds: function()
            {
                var me = this;
                
                for(var i=0,j=me.ids.length;i<j;i++)
                {
                    if(me.ids[i] == 'NaN') me.ids.splice(i, 1);
                }
            },
            setRecordsValue: function(view, record, item, index, e, eOpts, treeCombo)
            {
                var    me = treeCombo;
                
                me.fixIds();
                
                me.setValue(me.ids.join(','));
        
        
                me.fireEvent('itemclick', me, record, item, index, e, eOpts, me.records, me.ids);
        
        
                if(me.multiselect == false) me.onTriggerClick();
            }    
        });



    So this is actually a field.picker component where the tree is the picker and its aligned to look like a dropdown. I was trying to listen to the textfields "change" event, which gets fired whenever an input is entered or deleted into the textfield, however this does not get fired at all. Would i need to add the change event to the above code?
    In my controller, I can listen for the "itemclick" event on "treecombo". But the change event is never heard.
    Code:
    //controller
    
    
        init:function(){
          this.control({
            "treecombo":{
               "itemclick":function(){alert("item clicked");}//fires
            },
            "treecombo":{
               "change":function(){alert("changed");}//does NOT Fire
             }
           });
        }
    so it seems "treecombo" refers to the tree picker, and not the underlying textfield. So how can i listen for events on the textfield?


    thank you in advance...

  2. #2
    Sencha - Support Team
    Join Date
    Feb 2013
    Location
    California
    Posts
    6,375
    Vote Rating
    155
    Answers
    229
    Gary Schlosberg is a name known to all Gary Schlosberg is a name known to all Gary Schlosberg is a name known to all Gary Schlosberg is a name known to all Gary Schlosberg is a name known to all Gary Schlosberg is a name known to all

      0  

    Default

    Not sure it will be possible given that it is a picker rather than a combo as you mentioned. You might try contacting the author to see if this has been considered or partially implemented.
    http://www.sencha.com/forum/showthre...t.ux.TreeCombo
    Are you a Sencha products veteran who has wondered what it might be like to work at Sencha? If so, please reach out to our human resources manager: fabienne.bell@sencha.com

Thread Participants: 1

Tags for this Thread