We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 37108
    • 80 Posts
    I'm working on a CMP that stores some form data in a serialized fashion. For instance, I have two fields, msg_from_name and msg_from_addr, which save to the db field msg_from in this format: msg_from_addr|msg_from_name. I understand how to manipulate the data when retrieving with the prepareRow() method, but I don't know how to properly create/fill arbitrary fields (not directly related to a db field) in the MODext window/form ... and then post-process those on update, saving back to the single db field.

    Snippets of my best guess follow.

    In the grid file:
    Flexmail.grid.Campaigns = function(config) {
        config = config || {};
        Ext.applyIf(config,{
            id: 'flexmail-grid-campaigns'
            ,url: Flexmail.config.connectorUrl
            ,baseParams: { action: 'mgr/campaigns/getList' }
            ,fields: ['id','jobname','sourcedoc_id','createdon','modifiedon','send_end','msg_subj','msg_from','msg_replyto']
            ,paging: true
            ,remoteSort: true
            ,anchor: '97%'
            ,autoExpandColumn: 'name'
            ,columns: [{
                header: _('flexmail.campaigns.label_jobname')
                ,dataIndex: 'jobname'
                ,sortable: false
                ,width: 150
                ,editor: { xtype: 'textfield' }
            },{
                header: _('flexmail.campaigns.label_sourceid')
                ,dataIndex: 'sourcedoc_id'
                ,sortable: true
                ,width: 90
            },{
                header: _('flexmail.campaigns.label_createdon')
                ,dataIndex: 'createdon'
                ,sortable: true
                ,width: 90
            },{
                header: _('flexmail.campaigns.label_modifiedon')
                ,dataIndex: 'modifiedon'
                ,sortable: true
                ,width: 90
            },{
                header: _('flexmail.campaigns.label_senton')
                ,dataIndex: 'send_end'
                ,sortable: true
                ,width: 90
            }]
        });
        Flexmail.grid.Campaigns.superclass.constructor.call(this,config)
    };
    
    Ext.extend(Flexmail.grid.Campaigns,MODx.grid.Grid,{
        getMenu: function(){
            return [{
                text: _('flexmail.campaigns.menu_edit')
                ,handler: this.editCampaign
                },'-',{
                text: _('flexmail.campaigns.menu_delete')
                ,handler: this.deleteCampaign
                },'-',{
                text: _('flexmail.campaigns.menu_duplicate')
                ,handler: this.duplicateCampaign
            }];
        }
        ,editCampaign: function(btn,e){
            if(!this.editCampaignWindow){
                this.editCampaignWindow = MODx.load({
                    xtype: 'flexmail-window-campaign-edit'
                    ,record: this.menu.record
                    ,listeners: {
                        'success': {fn:this.refresh,scope:this}
                    }
                });
            }
            this.editCampaignWindow.setValues(this.menu.record);
            this.editCampaignWindow.show(e.target);
        }
    });
    
    Ext.reg('flexmail-grid-campaigns',Flexmail.grid.Campaigns);
    
    
    Flexmail.window.editCampaign = function(config){
        config = config || {};
        Ext.applyIf(config,{
            title: _('flexmail.campaigns.window_edit')
            ,url: Flexmail.config.connectorUrl
            ,baseParams: { action: 'mgr/campaigns/edit' }
            ,fields: [{
                    xtype: 'hidden'
                    ,name: 'id'
                },{
                    xtype: 'textfield'
                    ,fieldLabel: _('flexmail.campaigns.label_jobname')
                    ,name: 'jobname'
                    ,anchor: '100%'
                },{
                    xtype: 'textfield'
                    ,fieldLabel: _('flexmail.campaigns.label_email_subject')
                    ,name: 'msg_subj'
                    ,anchor: '100%'
                },{
                    xtype: 'textfield'
                    ,fieldLabel: _('flexmail.campaigns.label_email_from_name')
                    ,name: 'msg_from_name'
                    ,anchor: '100%'
                },{
                    xtype: 'textfield'
                    ,fieldLabel: _('flexmail.campaigns.label_email_from_addr')
                    ,name: 'msg_from_addr'
                    ,anchor: '100%'
            }]
        });
        Flexmail.window.editCampaign.superclass.constructor.call(this,config);
    };
    Ext.extend(Flexmail.window.editCampaign,MODx.Window);
    Ext.reg('flexmail-window-campaign-edit',Flexmail.window.editCampaign);
    


    In the getlist file:
    public function prepareRow(xPDOObject $object) {
            $objectArray = $object->toArray();
            $objectArray['createdon'] = date('m/d/Y',$object->get('createdon'));
            $objectArray['modifiedon'] = date('m/d/Y',$object->get('modifiedon'));
            
            $sent = $object->get('send_end');
            $objectArray['send_end'] = !empty($sent) ? date('m/d/Y',$sent) : 'Pending' ;
            
            $msg_from = $object->get('msg_from');
            $msg_from_arr = explode('|',$msg_from);
            
            $objectArray['msg_from_name'] = count($msg_from_arr)==2 ? $msg_from_arr[1] : '' ;
            $objectArray['msg_from_addr'] = $msg_from_arr[0];
            
            return $objectArray;
        }
    


    Any pointers?

    This question has been answered by smg6511v2. See the first response.

    [ed. note: smg6511v2 last edited this post 13 years, 9 months ago.]
      • 17403 ☆ A M B ☆
      • 183 Posts
      It's about javascript not about database in particular.

      For advanced solution you should look into ExtJS documentation. For example, in this documentation (http://docs.sencha.com/ext-js/3-4/#!/api/Ext.data.Store) you can find solution how to use Store to populate your form fields or data grid.

      Anyway, you said "in the grid file" but I don't see any grid in your script. It's only standard extjs form.
        zaenal.lokamaya
        • 37108
        • 80 Posts
        Thanks for the reply, lokamaya. I was hoping for a simpler method. Is there an example of this in action I could refer to (either in an existing extra or in the modx core) ... to get a better grasp of how to implement a custom Store?

        Also, originally I'd only posted a portion of my grid file. I've modified the original post to include the entire in-progress code ...
          • 17403 ☆ A M B ☆
          • 183 Posts
          I guess you already read http://rtfm.modx.com/display/revolution20/Developing+an+Extra+in+MODX+Revolution.

          Doodle extra have complete example how to display data in grid and update certain row in ExtJS. You can find it here https://github.com/splittingred/Doodles.
            zaenal.lokamaya
            • 37108
            • 80 Posts
            Yes, I've gone through that tut. It's great, but only addresses a very straight-forward data store.
              • 39194
              • 149 Posts
              I think you should merge your fields in the mgr/campaigns/edit processor, did you try it ?
                • 28840
                • 46 Posts
                In your 'mgr/campaigns/edit' file you receive the data as JSON encoded string. Correct?
                <?php
                /* parse JSON */
                if (empty($scriptProperties['data'])) return $modx->error->failure('Invalid data.');
                $_DATA = $modx->fromJSON($scriptProperties['data']);
                if (!is_array($_DATA)) return $modx->error->failure('Invalid data.');
                
                $msg_from = $_DATA['msg_from_addr'].'|'.$_DATA['msg_from_name'];
                $object = $modx->getObject('yourObject');
                $object->set('msgFrom',$msg_from);
                $object->save();
                


                This should do it...

                Sumoborac
                  • 37108
                  • 80 Posts
                  OK, I've resolved how to get the arbitrary fields' data into the update (edit) window. The grid js and getlist php is the same as originally posted ... I just needed to add the arbitrary fields (msg_from_addr & msg_from_name) into the field property in the grid code. Now, in the edit processor, I suppose I need to remove the arbitrary fields after merging/before save so as to not attempt writing data to non-existent db fields. May be back for help on this ... [ed. note: smg6511v2 last edited this post 13 years, 9 months ago.]
                    • 28840
                    • 46 Posts
                    you just set the fields which you have in DB... if you are using ->fromArray() then just unset() the fields you want.

                    Sumoborac
                    • discuss.answer
                      • 37108
                      • 80 Posts
                      OK, to summarize the other end (writing part) of the solution, I used the following in the beforeSave() method in my create and update classes:
                      public function beforeSave(){
                                      
                              $from_name = trim($this->getProperty('msg_from_name'));
                              $from_addr = trim($this->getProperty('msg_from_addr'));
                              $from = !empty($from_name) ? $from_addr.'|'.$from_name : $from_addr ;
                              
                              $reply_name = trim($this->getProperty('msg_reply_name'));
                              $reply_addr = trim($this->getProperty('msg_reply_addr'));
                              $replyto = !empty($reply_name) ? $reply_addr.'|'.$reply_name : $reply_addr ;
                      
                              $this->object->set('msg_from',$from);
                              $this->object->set('msg_replyto',$replyto);
                              
                              $this->unsetProperty('msg_from_name');
                              $this->unsetProperty('msg_from_addr');
                              $this->unsetProperty('msg_reply_name');
                              $this->unsetProperty('msg_reply_addr');
                              
                              return parent::beforeSave();
                          }
                      

                      Note, I also have a duplicate class, which seems to need alterations done in the beforeSet() method instead of beforeSave().

                      One thing I'm not certain of is whether I'm using unsetProperty() on the correct object ... but I don't seem to be getting any db errors.