We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 10378
    • 375 Posts
    Hello,

    are there any samples on how to read/write extended user fields through a CMP grid (MODx.window)?

    I already have the grid up and running and also the popup window which renders the extended fields as checkbox group.

    MODx Revo 2.2.5

    Greetings,
    Martin
      Freelancer @bitego http://www.bitego.com
      ---
      GoodNews - one of the most advanced and integrated Group Mailer premium add-ons for MODX Revolution!
      More infos here: http://www.bitego.com/extras/goodnews/
      • 10378
      • 375 Posts
      To give more details:

      I have a MODx.grid which lists users from the user table of MODx. Right clicking a user in this grid opens a MODx.Window. This MODx.Window loads a list of categories from a custom table and renders it as a CheckboxGroup (generated by a JsonStore).
      This works fine so far.
      I'm also already writing back the values to the extended field of the user.

      The problem is - at load time of the CheckboxGroup - I have to match which categories the user already has in his extended fields and set the corresponding checkbox to "checked".

      How can this be done? I didn't find any help in the MODx sources and the ExtJS documentation also doesn't show me the right direction. I'm currently helpless!

      We are working on a newsletter extra which uses the built in user table for subscriptions as well as resource containers as newsletter store. This extra will be released as open source.
        Freelancer @bitego http://www.bitego.com
        ---
        GoodNews - one of the most advanced and integrated Group Mailer premium add-ons for MODX Revolution!
        More infos here: http://www.bitego.com/extras/goodnews/
        • 10378
        • 375 Posts
        And here are the sources:

        The grid with the edit window

        Line 175 calls the JsonStore function which generates the checkbox group

        GoodNews.grid.Subscribers = function(config){
            config = config || {};
        
            Ext.applyIf(config,{
                id: 'goodnews-grid-subscribers'
                ,url: GoodNews.config.connectorUrl
                ,baseParams: { action: 'mgr/subscribers/getList' }
                ,fields: [
                    'id'
                    ,'username'
                    ,'fullname'
                    ,'email'
                    ,'newslettercategories'
                    ,'extended'
                    ,'menu'
                ]
                ,emptyText: _('goodnews.subscribers_none')
                ,paging: true
                ,remoteSort: true
                ,columns: [{
                    header: _('goodnews.subscriber_username')
                    ,dataIndex: 'username'
                    ,sortable: true
                    ,width: 100
                },{
                    header: _('goodnews.subscriber_fullname')
                    ,dataIndex: 'fullname'
                    ,sortable: true
                    ,width: 100
                },{
                    header: _('goodnews.subscriber_email')
                    ,dataIndex: 'email'
                    ,sortable: true
                    ,width: 100
                },{
                    header: _('goodnews.subscriber_categories')
                    ,dataIndex: 'newslettercategories'
                    ,width: 100
                },{
                    header: 'Extended (debug)'
                    ,dataIndex: 'extended'
                    ,width: 100
                }]
                ,tbar:['->',{
                    xtype: 'modx-combo-usergroup'
                    ,name: 'usergroup'
                    ,id: 'goodnews-user-filter-usergroup'
                    ,itemId: 'usergroup'
                    ,emptyText: _('goodnews.subscribers_user_group')+'...'
                    ,baseParams: {
                        action: 'getList'
                        ,addAll: true
                    }
                    ,value: MODx.request['usergroup'] ? MODx.request['usergroup'] : ''
                    ,width: 200
                    ,listeners: {
                        'select': {fn:this.filterUsergroup,scope:this}
                    }
                },'-',{
                    xtype: 'textfield'
                    ,id: 'goodnews-subscribers-search-filter'
                    ,emptyText: _('goodnews.subscribers_search...')
                    ,listeners: {
                        'change': {fn:this.search,scope:this}
                        ,'render': {fn: function(cmp) {
                            new Ext.KeyMap(cmp.getEl(), {
                                key: Ext.EventObject.ENTER
                                ,fn: function() {
                                    this.fireEvent('change',this);
                                    this.blur();
                                    return true;
                                }
                                ,scope: cmp
                            });
                        },scope:this}
                    }
                },{
                    xtype: 'button'
                    ,id: 'goodnews-subscribers-filter-clear'
                    ,text: _('filter_clear')
                    ,listeners: {
                        'click': {fn: this.clearFilter,scope:this}
                    }
                }]
            });
            GoodNews.grid.Subscribers.superclass.constructor.call(this,config);
        };
        Ext.extend(GoodNews.grid.Subscribers,MODx.grid.Grid,{
            getMenu: function() {
                var r = this.getSelectionModel().getSelected();
                var p = r.data.perm;
        
                return [{
                    text: _('goodnews.subscriber_update')
                    ,handler: this.updateSubscriber
                },'-',{
                    text: _('goodnews.user_update')
                    ,handler: this.updateUser
                }];
            }
            ,updateSubscriber: function(btn,e) {
                //needs to be destroyed in order to recreate checkboxgroup!
                if (this.updateSubscriberWindow) {
                    this.updateSubscriberWindow.destroy();
                }
                this.updateSubscriberWindow = MODx.load({
                    xtype: 'goodnews-window-subscriber-update'
                    ,record: this.menu.record
                    ,scope: this
                    ,listeners: {
                        'success': {fn:this.refresh,scope:this}
                    }
                });
                this.updateSubscriberWindow.setValues(this.menu.record);
                this.updateSubscriberWindow.show(e.target);
            }
            ,updateUser: function(btn,e) {
                location.href = 'index.php?a='+MODx.action['security/user/update']+'&id='+this.menu.record.id;
            }
            ,filterUsergroup: function(cb,nv,ov) {
                this.getStore().baseParams.usergroup = Ext.isEmpty(nv) || Ext.isObject(nv) ? cb.getValue() : nv;
                this.getBottomToolbar().changePage(1);
                this.refresh();
                return true;
            }
            ,search: function(tf,nv,ov) {
                var s = this.getStore();
                s.baseParams.query = tf.getValue();
                this.getBottomToolbar().changePage(1);
                this.refresh();
            }
            ,clearFilter: function() {
            	this.getStore().baseParams = {
                    action: 'mgr/subscribers/getList'
            	};
                Ext.getCmp('goodnews-subscribers-search-filter').reset();
                Ext.getCmp('goodnews-user-filter-usergroup').reset();
            	this.getBottomToolbar().changePage(1);
            }
        });
        Ext.reg('goodnews-grid-subscribers',GoodNews.grid.Subscribers);
        
        
        GoodNews.window.UpdateSubscriber = function(config) {
            config = config || {};
            
            console.log(this);
        
            Ext.applyIf(config,{
                title: _('goodnews.subscriber_update')
                ,url: GoodNews.config.connectorUrl
                ,baseParams: {
                    action: 'mgr/subscribers/update'
                }
                ,fields: [{
                    xtype: 'hidden'
                    ,name: 'id'
                },{
                    xtype: 'displayfield'
                    ,fieldLabel: 'extended field'
                    ,name: 'extended'
                    ,readOnly: true
                },{
                    xtype: 'displayfield'
                    ,fieldLabel: _('goodnews.subscriber_username')
                    ,name: 'username'
                    ,readOnly: true
                },{
                    id: 'cat-ext-checkboxgroup'
                    ,fieldLabel: _('goodnews.subscriber_categories')
                    ,name: 'newslettercategories'
                    ,listeners: {
                        'render': {
                            fn: function() {
                                catCheckboxGroup('cat-ext-checkboxgroup','newslettercategories');
                            }
                        }
                    }
        
                }]
            });
            GoodNews.window.UpdateSubscriber.superclass.constructor.call(this,config);     
        };
        Ext.extend(GoodNews.window.UpdateSubscriber,MODx.Window);
        Ext.reg('goodnews-window-subscriber-update',GoodNews.window.UpdateSubscriber);
        



        The JsonStore function

        This function generates the checkbox group. The problem is, I don't know how to match the list of categories (mgr/category/getList) with the list of categories the user has already in his extended fields - to set the corresponding checkboxes to checked.

        function catCheckboxGroup(renderTarget,groupName) {
            Ext.onReady(function() {
                var catStore = new Ext.data.JsonStore({
                    url: GoodNews.config.connectorUrl
                    ,baseParams: {
                        action: 'mgr/category/getList'
                    }
                    ,fields: ['id','name','uniquekey']
                    ,root: 'results'
                    ,autoLoad: false
                    ,autoDestroy: true
                    ,listeners: {
                        'load': {
                            fn: function(t, records, options, success) {
                                var catArray = [];
                                for (var i=0; i<records.length; i++) {
                                    catArray.push({
                                        name: groupName+'['+records[i].data.uniquekey+']'
                                        ,inputValue: records[i].data.id
                                        ,boxLabel: records[i].data.name
                                    });
                                }
                                var catCheckboxGroup = new Ext.form.CheckboxGroup({
                                    items: catArray
                                    ,columns: 2
                                    ,renderTo: renderTarget
                                });
                                //console.log(catArray);
                            }
                        }
                        /*,'loadexception': {
                            fn: function(obj, options, response, e){
                                console.info('store loadexception, arguments:', arguments);
                                console.info('error = ', e);
                            }
                        }*/
                    }
                });
                catStore.load();
            });
        };
        



        The processor part (used in the JsonStore function)

        <?php
        class CategoryGetListProcessor extends modObjectGetListProcessor {
            public $classKey = 'GoodNewsCategory';
            public $languageTopics = array('goodnews:default');
            public $defaultSortField = 'name';
            public $defaultSortDirection = 'ASC';
            public $objectType = 'goodnews.category';
        
            public function prepareQueryBeforeCount(xPDOQuery $c) {
                $query = $this->getProperty('query');
                if (!empty($query)) {
                    $c->where(array(
                        'name:LIKE' => '%'.$query.'%',
                        'OR:description:LIKE' => '%'.$query.'%',
                        'OR:uniquekey:LIKE' => '%'.$query.'%',
                    ));
                }
                return $c;
            }
        
            public function prepareRow(xPDOObject $object) {
                $resourceArray = parent::prepareRow($object);
        
        
        
        
                return $resourceArray;
            }
        
        }
        return 'CategoryGetListProcessor';
        
        [ed. note: gadgetto last edited this post 13 years, 10 months ago.]
          Freelancer @bitego http://www.bitego.com
          ---
          GoodNews - one of the most advanced and integrated Group Mailer premium add-ons for MODX Revolution!
          More infos here: http://www.bitego.com/extras/goodnews/
          • 38209
          • 26 Posts
          So if I'm correct, you can already read (view) the fields...just not edit them, right?
            • 29661
            • 116 Posts
            I think, that store user categories and retrieving them should be more easier with new table, where you store user id and category id. You can do pretty fast join with this ang get just categories to specific user.
              --
              John
              @theboxer
              • 10378
              • 375 Posts
              Quote from: scherpontwikkeling at Nov 26, 2012, 02:07 AM
              So if I'm correct, you can already read (view) the fields...just not edit them, right?

              Hi and thanks for your help,

              I can read the categories from our custom newsletter categories table and display them as a list of checkboxes (CheckboxGroup) - please have a look at the screenshot update_subscriptions_window.png.
              And I can already save checked values to the extended field of the user (as an array) - screeenshot user_extended_fields.png.
              The array has a json format of: {"newslettercategories":{"test2":"37","test":"36"}}

              What I wasn't able to figure out is how to match the categories the user already has in his extended fields and set the corresponding checkbox to "checked" when the popup window loads. Currently the window only loads the list of checkboxes without the checked status.
                Freelancer @bitego http://www.bitego.com
                ---
                GoodNews - one of the most advanced and integrated Group Mailer premium add-ons for MODX Revolution!
                More infos here: http://www.bitego.com/extras/goodnews/
                • 38209
                • 26 Posts
                Ah, now I know where you are going...so you are developing a custom component (completely separate from the MODX user management, which wasn't really clear for me). This is just a basic EXT question...

                I would suggest you build a simple grid in the window (one like you have in the backend) with a contextmenu on each row (edit, delete). Above the grid create a form with the fields 'key' and 'value' and an 'Add' button. Enter the key and value, make a click handler on the button that posts the values to a processor that adds these value to a user.

                In the contextmenu (the edit function) you can just fill the same form with the existing values and change the 'add' text of the button to 'update'. We have applied this principle in visioncart as well (check the screenshot attachment).

                I assume you know how to update the extended fields through PHP code?
                  • 38209
                  • 26 Posts
                  By the way, I have the example script right here...you can extract the contextmenu example and principle here...this is not copy paste for your application but you can get the EXT code from this...
                    • 10378
                    • 375 Posts
                    Quote from: scherpontwikkeling at Nov 26, 2012, 04:37 AM
                    Ah, now I know where you are going...so you are developing a custom component (completely separate from the MODX user management, which wasn't really clear for me). This is just a basic EXT question...

                    I think I still couldn't explain what I want.

                    We are developing a MODx newsletter component which uses a custom table for newsletter categories. These categories are used to filter which mails a subscriber will get. The subscribers are managed in the default user table of MODx (not separated from the MODx user management). And those users will have their categories stored in extended fields (in the form of: "name_of_category","id_of_category").

                    Our CMP has a grid which lists users from the MODx user table. An admin user should be able to assign (and remove) the newsletter categories for a user (with a simple check or uncheck of a checkbox field).
                    I can't ask an admin to manually enter the values in the form of: "name_of_category","id" - as he normally doesn't know the exact values/ids. So I cant use your method you suggested.

                    In short:

                    We have a custom table on one side and the MODx user table with it's extended fields on the other side. The values from the custom table should be stored in the users extended fields.
                      Freelancer @bitego http://www.bitego.com
                      ---
                      GoodNews - one of the most advanced and integrated Group Mailer premium add-ons for MODX Revolution!
                      More infos here: http://www.bitego.com/extras/goodnews/
                      • 10378
                      • 375 Posts
                      It would also help if someone could show/tell me how to send the value of the field "extended" (which I already have available in the MODx.window) to my JsonStore function. The function call is in line 175 of the first source a few posts above.

                      I dont know how to access the value of "extended" field from the MODx.window and send it to the JsonStore function. #javascriptnoob ;-)
                        Freelancer @bitego http://www.bitego.com
                        ---
                        GoodNews - one of the most advanced and integrated Group Mailer premium add-ons for MODX Revolution!
                        More infos here: http://www.bitego.com/extras/goodnews/