1. #1
    Ext User
    Join Date
    Feb 2010
    Posts
    6
    Vote Rating
    0
    Cannon is on a distinguished road

      0  

    Question Comboboxs that are dependent on value from others in a Grid

    Comboboxs that are dependent on value from others in a Grid


    i am constucting an ediatble grid to log time spent on specific projects.

    it has fields for date and time, as well as the job that was worked on.

    Jobs belong to a project, which belong to a client

    I need a way to create this behavior in my grid

    a user selects a client from the clients combo box
    the projects combo-box should now only contain projects that belong to that client
    when they select a proejct i want the jobs lsit to do the same.

    i was able to achieve this with a on("change"...) listener, but it rerenders every record in my grid, causing their values to not be displayed

    is there a way to only manipulate one row's editor without screwing with all of them?



    a screen shot :
    entries grid.png
    and heres the source :


    Code:
    // Application instance for showing user-feedback messages.
    var App = new Ext.App({});
    
    // Create a standard HttpProxy instance.
    var proxy = new Ext.data.HttpProxy({
        api: {
            read: {
                url: '/entries.xml',
                method: 'GET'
            }, create: {
                url: '/entries.xml',
                method: 'POST'
            }, update: {
                url: '',
                method: 'PUT'
            }, destroy: {
                url: '',
                method: 'DELETE'
            }
        }
    });
    var reader = new Ext.data.XmlReader({
        record: 'entry',
        id: 'id'
    }, [{
        name: 'day',
        type: 'date',
        dateFormat: 'Y-m-d'
    }, {
        name: 'job-id'
    }, {
        name: 'project-id'
    }, {
        name: 'client-id'
    }, {
        name: 'time',
        type: 'float'
    }, {
        name: 'submitted',
        type: 'boolean'
    }]);
    // The new DataWriter component.
    var writer = new Ext.data.XmlWriter({
        root: 'entries'
    
    });
    // Typical Store collecting the Proxy, Reader and Writer together.
    var store = new Ext.data.GroupingStore({
        //restful: true,
        // <-- This Store is RESTful
        proxy: proxy,
        reader: reader,
        writer: writer,
        // <-- plug a DataWriter into the store just as you would a Reader
        sortInfo: {
            field: 'day',
            direction: "DSC"
        }, groupField: 'day',
        batch: false
    });
    
    store.load(); // load the store immeditately
    ////
    // centralized listening of DataProxy events "beforewrite", "write" and "writeexception"
    // upon Ext.data.DataProxy class.  This is handy for centralizing user-feedback messaging into one place rather than
    // attaching listenrs to EACH Store.
    //
    // Listen to all DataProxy beforewrite events
    //
    Ext.data.DataProxy.addListener('beforewrite', function (thisProxy, action, rs) {
      
         if (thisProxy == proxy) {
            thisProxy.setApi({
                read: {
                    url: '/entries.xml',
                    method: 'GET'
                }, create: {
                    url: '/entries.xml',
                    method: 'POST'
                }, update: {
                    url: '/entries/' + rs.id + '.xml',
                    method: 'PUT'
                }, destroy: {
                    url: '/entries/' + rs.id + '.xml',
                    method: 'DELETE'
                }
            });
            if (rs.modified)
            {
              if (!(rs.modified['job-id']||rs.modified['time']||rs.modified['date']||rs.modified['submitted'] ) )
               {
                  return false;
                }
             }
            
            }
            
        
      
        
    
        //  App.setAlert(App.STATUS_NOTICE, "Before " + action);
    });
    
    ////
    // all write events
    //
    Ext.data.DataProxy.addListener('write', function (proxy, action, result, res, rs) {
        App.setAlert(true, action);
    });
    
    ////
    // all exception events
    //
    Ext.data.DataProxy.addListener('exception', function (proxy, type, action, options, res) {
        App.setAlert(false, res.responseText);
    
    
    });
    
    function formatDate(value) {
        return value ? value.dateFormat('M d, Y') : '';
    }
    
    
    var summary = new Ext.ux.grid.GroupSummary();
    
    var jobsProxy = new Ext.data.HttpProxy({
        api: {
            read: {
                url: '/jobs.xml',
                method: 'GET'
            }
        }
    });
    var jobsReader = new Ext.data.XmlReader({
        record: 'job',
        id: 'id'
    }, [{
        name: 'id',
        type: 'integer'
    }, {
        name: 'name',
        type: 'string'
    }, {
        name: 'project_id',
        type: 'integer'
    }]);
    
    
    
    
    
    var clientsProxy = new Ext.data.HttpProxy({
        api: {
            read: {
                url: '/clients.xml',
                method: 'GET'
            }
        }
    });
    var clientsReader = new Ext.data.XmlReader({
        record: 'client',
        id: 'id'
    }, [{
        name: 'id',
        type: 'integer'
    }, {
        name: 'name',
        type: 'string'
    }]);
    
    
    
    var projectsProxy = new Ext.data.HttpProxy({
        api: {
            read: {
                url: '/projects.xml',
                method: 'GET'
            }
        }
    });
    var projectsReader = new Ext.data.XmlReader({
        record: 'project',
        id: 'id'
    }, [{
        name: 'id',
        type: 'integer'
    }, {
        name: 'name',
        type: 'string'
    }, {
        name: 'client_id',
        type: 'ineger'
    }]);
    
    
    
    
    
    
    
        var clientsCombo = new Ext.form.ComboBox({
            store: new Ext.data.Store({
                    proxy: clientsProxy,
                    reader: clientsReader
                  }),
            mode: 'local',
            typeAhead: true,
            typeAheadDelay: 10,
            triggerAction: 'all',
            width:135,
            lazyRender: true, 
            forceSelection:true,
            valueNotFoundText: 'Select a Client...',
            valueField: 'id',
            displayField: 'name'
    });
    clientsCombo.store.load();
    
           var projectsCombo = new Ext.form.ComboBox({
            store: new Ext.data.Store({
        proxy: projectsProxy,
        reader: projectsReader
    }),
            mode: 'local',        
            typeAhead: true,
            typeAheadDelay: 10,
            triggerAction: 'all',
            width:135,
            lazyRender: true, 
            valueNotFoundText: 'Select a Project...',
            valueField: 'id',
            displayField: 'name'
    });
    projectsCombo.store.load();
         var jobsCombo = new Ext.form.ComboBox({
            store: new Ext.data.Store({
        proxy: jobsProxy,
        reader: jobsReader
    }),
            mode: 'local',
            typeAhead: true,
            typeAheadDelay: 10,
            triggerAction: 'all',
            width:135,
            lazyRender: true, 
            valueNotFoundText: 'Select a Job...',
            valueField: 'id',
            displayField: 'name'
    });
    jobsCombo.store.load();
    clientsCombo.on('change', function(field , newVal , oldVal) {
    //console.group('clientsCombo on change')
    //console.dir( field, newVal,oldVal)
    //console.groupEnd();
      if (!field.value.match(/^Select/i))
      {
        projectsCombo.store.filter('client_id',  field.value);
      }  
    });
    projectsCombo.on('change', function(field , newVal , oldVal) {
      if (!field.value.match(/^Select/i))
      {
      jobsCombo.store.filter('project_id' ,field.value );
      }
    });
    
    
    Ext.onReady(function () {
    
    
       function refreshGridOnLoad(store) {
          if (!store.loadCounter)
          {
             if (userGrid) 
             {
              userGrid.view.refresh()
             }
              store.loadCounter = 0;
         }
         store.loadCounter++;
       }   
    
    
    jobsCombo.store.on('load' , refreshGridOnLoad)
    projectsCombo.store.on('load' , refreshGridOnLoad)
    clientsCombo.store.on('load' , refreshGridOnLoad)
    
    
        Ext.util.Format.comboRenderer = function (combo) {
            return function (value) {
                if (!value) {
                    return combo.valueNotFoundText;
                } else {
                    var record = combo.findRecord(combo.valueField, value);
                    return record ? record.get(combo.displayField) : combo.valueNotFoundText;
                }
            }
        };
    
    
    
        var userColumns = [{
            header: "Date",
            width: 50,
            dataIndex: 'day',
            editor: new Ext.form.DateField({
                format: 'd/m/y'
            }),
            renderer: formatDate,
            sortable: true
        },{
            header: "Client",
            width: 70,
            dataIndex: 'client-id',
            editor: clientsCombo,
            renderer: Ext.util.Format.comboRenderer(clientsCombo)
        }, {
            header: "Project",
            width: 70,
            dataIndex: 'project-id',
            editor: projectsCombo,
            renderer: Ext.util.Format.comboRenderer(projectsCombo)
        }, {
            header: "Job",
            width: 70,
            dataIndex: 'job-id',
            editor: jobsCombo,
            renderer: Ext.util.Format.comboRenderer(jobsCombo)
        }, {
            header: "Hours",
            width: 50,
            dataIndex: 'time',
            summaryType: 'sum',
            editor: new Ext.form.NumberField({
                allowBlank: false,
                allowNegative: false,
                maxValue: 24
            }),
            renderer: function (value) {
    
    
    
                if (value) {
                    if (value <= 24) {
                        return value + " hours"
                    }
                    else if (value > 24) {
                        return "<div class='x-grid3-summary-err'>" + value + " hours ?</div>"
                    }
                }
                else if (!value) {
                    return "0 hours"
                }
    
            }
        }
        ];
    
    
    
    
    
        // Create a typical GridPanel with RowEditor plugin
        var userGrid = new Ext.grid.EditorGridPanel({
            renderTo: 'user-grid',
            // iconCls: 'icon-grid',
            frame: true,
            title: 'Entries',
            autoScroll: true,
            height: 500,
            store: store,
            clicksToEdit: 1,
            plugins: summary,
            columns: userColumns,
            tbar: [{
                text: 'Add',
                // iconCls: 'silk-add',
                handler: onAdd
            }, '-', {
                text: 'Delete',
                //  iconCls: 'silk-delete',
                handler: onDelete
            }, '-', {
                text: 'Submit To Management',
                handler: onSubmitToManagement
            }],
            view: new Ext.grid.GroupingView({
                forceFit: true,
            })
    
    
        });
    
    
    
    
    
    
        /**
         * onAdd
         */
    
        function onAdd() {
            var e = new userGrid.store.recordType({
                day: (new Date()).clearTime(),
                project_id: 0,
                hours: 0
            });
            userGrid.stopEditing();
            userGrid.store.insert(0, e);
            userGrid.startEditing(0);
        }
        /**
         * onDelete
         */
        function onDelete() {
            var index = userGrid.getSelectionModel().getSelectedCell();
            if (!index) {
                return false;
            }
    
            var rec = userGrid.store.getAt(index[0]);
    
            userGrid.store.remove(rec);
        }
        /**
         * onSubmitToManagement
         * & hleper functions 
         */
        function onSubmitToManagement() {
            Ext.Msg.confirm("Death be upon you", "you hereby forgo any right to your soul, past present and future, it will be harvested immediately, Are these terms acceptable?", areYouReallySure)
        }
    
        function areYouReallySure(btn) {
            if (btn == 'yes') {
                Ext.Msg.confirm("Are you sure", "cause it really hurts to have your soul ripped out....", submitEntries)
            }
        }
    
        function submitEntries(btn) {
            if (btn == 'yes') {
                console.log("submitting")
                   userGrid.store.each(function submit() {
                       this.beginEdit()
                    this.set('submitted', true);
                       this.endEdit()
                    this.commit()
                 return true;
                })
                   store.filterBy(function (rec, id) {
                       if (rec.get('submitted')) {
                        return false;
                    }
                    else {
                        return true;
                    }
                })
    
                userGrid.view.refresh()
    
            }
        }
    
        userGrid.on('afteredit', function (e) {
            e.grid.view.refresh()
            
      
        })
    });

  2. #2
    Ext JS Premium Member
    Join Date
    Jun 2010
    Posts
    11
    Vote Rating
    0
    johnholden is on a distinguished road

      0  

    Default


    I have the exact same problem. Does anyone know of a solution, or better way to handle this situation in general?

  3. #3
    Sencha - Community Support Team Condor's Avatar
    Join Date
    Mar 2007
    Location
    The Netherlands
    Posts
    24,246
    Vote Rating
    94
    Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of

      0  

    Default


    The correct way to handle this is to filter (or load) the combobox store in the beforeedit event of the grid cell.

  4. #4
    Ext User
    Join Date
    Feb 2010
    Posts
    6
    Vote Rating
    0
    Cannon is on a distinguished road

      0  

    Lightbulb solution

    solution


    would have been nice to have reply that fast when i posted...
    i want to say i tried that and id didnt work for some reason but i ended up loading a store on focus event, with url parameters to filter it based on previousSibling's value, then load the full list again on blur event.

    so for each row you edit you send like 6 ajax requests ( with 3 combos ) but it works for me


    jobs belong to projects which belong to clients,

    select a client, get a list of its projects, get a list of its jobs

    Code:
       projectsCombo.on('focus' , function(field){
             var client = field.previousSibling().value; // get last fields value
             if (client ){
                 if (!client.match(/^Select/i)){ \\ if the value isnt the default  'select a ___'  text in the combo
                     projectsCombo.store.load({params:'client_id=' + client} ) // load a filtered store
                 }
             }
         }
       )
       jobsCombo.on('focus' , function(field){
            var project = field.previousSibling().value;
            if (project){
                if (!project.match(/^Select/i)){
                    jobsCombo.store.load( { params: 'project_id=' + project } )
                }
            }
         }
       )
       projectsCombo.on('blur' , function(field){
             projectsCombo.store.load({params:''} ) //reutrn to global list
         }
       )
       jobsCombo.on('blur' , function(field){
            jobsCombo.store.load( { params: '' } )
         }
       )
    Last edited by Cannon; 30 Nov 2010 at 1:58 PM. Reason: add comments

Similar Threads

  1. Grid with Dependent Stores
    By smartinec in forum Ext 2.x: Help & Discussion
    Replies: 5
    Last Post: 26 Jun 2010, 1:15 AM
  2. Lines of a dependent grid may not show completely
    By Pachat in forum Ext 3.x: Help & Discussion
    Replies: 1
    Last Post: 21 Apr 2010, 4:33 PM
  3. Strange behavior of ComboBoxs
    By lithian in forum Community Discussion
    Replies: 0
    Last Post: 19 Oct 2007, 1:00 AM
  4. need help adding time selector in form using comboboxs
    By rdesroches in forum Ext 1.x: Help & Discussion
    Replies: 2
    Last Post: 22 Aug 2007, 5:39 AM
  5. Dependent Grids = How to
    By ramanbasu in forum Community Discussion
    Replies: 1
    Last Post: 19 May 2007, 2:22 AM

Thread Participants: 2

Tags for this Thread