We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 36695
    • 47 Posts
    Hi,
    I've read a number of posts about using the combo box element, but I seem to be missing something really basic.
    I have a plugin that fires on the OnUserFormRender (and Prerender/Save) event. I can successfully get my custom data values and save them if I render a simple text box a la Adding Custom fields tutorial.
    My plugin looks a little like this:
    switch($modx->event->name) {
    		case 'OnUserFormPrerender':
    		//Presumably need to add some JS here
    		break;
    		case 'OnUserFormRender':
    		//Some fancy stuff here to get my extended user data values or a default one if a new user
    		$fields = 'html output stuff. Can successfully output a text field with name "newsletter"';
    		$modx->event->output($fields);
    		break;
    		case 'OnUserFormSave':
    //Get the custom field value ("newsletter") from $_POST and save it
    		break;
    }
    


    In the prerender event I've tried loading some JS like this:

    Userform.combo.Newsletter = function(config) {
        config = config || {};
        Ext.applyIf(config,{
            store: new Ext.data.ArrayStore({
                id: 0
                ,fields: ['newsletter','display']
                ,data: [
                    ['0','No']
                    ,['1','Yes']
                ]
            })
            ,mode: 'local'
            ,displayField: 'display'
            ,valueField: 'newsletter'
        });
        Userform.combo.Newsletter.superclass.constructor.call(this,config);
    };
    Ext.extend(Userform.combo.Newsletter,MODx.combo.ComboBox);
    Ext.reg('userform-combo-newsletter',Userform.combo.Newsletter);
    


    With the result that I get "Userform is not defined" errors. I tried outputting "<div id="userform-combo-newsletter"></div>" from the OnUserFormRender event too.

    The combo box docs say I need something like the code below, but I'm not sure where this should go in order to "startup" the combo box element:
    { xtype: 'userform-combo-newsletter'
                ,fieldLabel: 'Newsletter'
                ,name: 'newsletter'
                ,hiddenName: 'newsletter'
                ,anchor: '100%'
    }
    

    I tried adding it using:
    Ext.onReady(function() {
    			    MODx.load( 
    //the object above
    )});
    

    But I guess that was just wishful thinking.

    Any pointers would be very welcome.
      • 36695
      • 47 Posts
      OK so a lot of messing about later I have found a way to extend the user form with whatever I like, so thought I'd post it in case anyone stumbled on this question.
      Using a plugin that fires on "OnUserFormPrerender" you can add a js file (with $modx->regClientStartupScript($src)) that grabs the user form tabs object and then extends it:
      Ext.onReady(function() {
      
      	var usertabs = Ext.getCmp('modx-user-tabs');
      	usertabs.add({
      		
      		title: 'My Tab ' + (usertabs.items.length + 1),
      		defaults: { labelWidth: 180 },
      		layout: 'form',
      		autoScroll: true,
      		autoHeight: false,
      		labelAlign: "left",
      		labelWidth: 180,
      		width: 800,
      		height: 500,
      		cls: 'main-wrapper',
      		items: [
      			{
      				xtype: 'combo-boolean'
      				,name: 'mybooleanfield'
      				,fieldLabel: 'Set a value for my boolean field or use a lexicon string'
      				,value: 1
      				,allowBlank: false
      
      			}
      			,{
      				html: '<p>Some instructions for the field below</p>'
      				,border: false
      , bodyCssClass: 'panel-desc'
      			}
      			,{
      				xtype: 'xdatetime'
      				,fieldLabel: 'Renewal date'
      				,name: 'renewal_date'
      				,allowBlank: true
      			}
      			,{
      				fieldLabel: 'Whoa! a super select box!',
      				id: 'licences-superbox-primarylicenses',
      				name: 'primarylicences[]',
      				xtype: 'modx-superbox-primarylicences',
      				resizable: true
      			}
      
      		]
      	});
      
      });
      


      If you're interested the superboxselect xtype "modx-superbox-primarylicences" used as one of the items above can be defined like this (I've just added mine in the same file as the tabs extension above, but if it's reuseable code then it should probably be in a separate file):
      /**
       * PrimaryLicences SuperBoxSelect
       *
       * @class MODx.combo.PrimaryLicences
       * @extends Ext.ux.form.SuperBoxSelect
       * @xtype modx-superbox-primarylicences
       */
      MODx.combo.PrimaryLicences = function (config) {
      	config = config || {};
      	Ext.applyIf(config, {
      		xtype:'superboxselect'
      		,triggerAction: 'all'
      		,mode: 'remote'
      		,valueField: "id"
      		,displayField: "fullname"
      		,typeAhead: true
      		,typeAheadDelay:75
      		,width: 400
      		,pageSize: 20
      		,store: new Ext.data.JsonStore({
      			id:'id',
      			autoLoad: true,
      			root:'results',			
      			dir: 'ASC',
      			fields: ['fullname', 'id'],
      			url: MODx.config.connectors_url+'security/user.php',
      			baseParams:{
      				action: 'getList'
      				,usergroup: 2
      				,sort: 'fullname'
      				,dir: 'ASC'
      			}
      		})
      	});
      	MODx.combo.PrimaryLicences.superclass.constructor.call(this, config);
      };
      Ext.extend(MODx.combo.PrimaryLicences, Ext.ux.form.SuperBoxSelect);
      Ext.reg('modx-superbox-primarylicences', MODx.combo.PrimaryLicences );
      


      Again for reference, one of the tab items I included above is a datetime field. On the User form the datetime.js utility file is already loaded, but if you're using this technique to extend a form that doesn't already load it, or on a CMP page, you need to explicitly add the datetime file before you can add an xdatetime xtype. e.g. in a CMP controller file add
      $this->addJavascript(MODX_MANAGER_URL.'assets/modext/util/datetime.js');
      

      to your loadCustomCssJs method. If you're using it in a plugin you can probably use regClientStartupScript to add the file. Then you can add a datetime element to your panel with something like
      items: [{
      	xtype: 'xdatetime',
      	name: 'renewal_date',
      	//other properties
      	},
      	{
      	//...other items
      	}
      ]
      



      Obviously you can add whatever other form elements you like under the "items" property of the new tab (the datetime and superboxselect elements shown above were just examples of doing something fancy that made me smile). On save the fields will be submitted along with the rest of the form, so your same plugin can capture the event OnUserFormSave in order to process your fields.
      In my case, I have extended the modUser object and this is how I'm managing the extended object's values.
        • 38290
        • 712 Posts
        This is great! I just posted about how I'm starting working on a Humans Addon that manages creating your humans.txt file you and something like this is one of the desired features
        https://forums.modx.com/thread/80630/humans-txt-manager-addon#dis-post-444213
          jpdevries
          • 17403 ☆ A M B ☆
          • 183 Posts
          Great post!
          I need that ExtJS stuff ^_^


          I'm also currently making a plugin for customizing create/update resource (not users form), and found some interesting stuff.

          (1) I just know that OnDocFormRender has been executed before OnDocFormPrerender (uh, silly me, I posted it here https://forums.modx.com/thread/80538/plugin-system-events-sequences). And I guess OnUserFormRender also precedes OnUserFormPrerender.

          (2) Resource's form and it's elements has been generated on the fly using javascript. So using regClientStartupScript is not a choice (if we want to modify the form), because we have no control for javascript pooling (what script will be executed first).

          (3) The safe method is by injecting javascript using $modx->event->output on OnDocFormPrerender event. Maybe it's also applicable for OnUserFormPrerender.

          Here is my approach...

          <?php
          /**
           * MYADDON plugin
          **/
          switch ($modx->event->name) {
              case 'OnDocFormRender':
                  $processOnPrerender = false;
                  $customAction  = '<input type="hidden" name="customAction" value="MYADDON" />' . "\n";
                  
                  if ($mode == modSystemEvent::MODE_NEW) {
                      //if match something on creating resource: make global variable
                      global $processOnPrerender;
                      $processOnPrerender = true;
                  } elseif ($mode == modSystemEvent::MODE_UPD) {
                      //if match something on updating resource: make global variable
                      global $processOnPrerender;
                      $processOnPrerender = true;
                  }
                  if ($processOnPrerender) {
                      //to make sure everything okay OnDocFormSave...
                      $modx->event->output($customAction);
                  }
                  break;
              case 'OnDocFormPrerender':
                  global $processOnPrerender;
                  if (isset($processOnPrerender) && $processOnPrerender === true) {
                      $MYADDONpath = $modx->getOption('MYADDON.assets_url',null,$modx->getOption('assets_url').'components/MYADDON/');
          
                      $script  = '<script type="text/javascript" src="'.$MYADDONpath . 'mgr/resource-form.js'.'"></script>' . "\n";
                      $script .= '<style type="text/css" href="'.$MYADDONpath . 'mgr/resource-form.css'.'"></style>' . "\n";
                      $modx->event->output($script);
                  }
                  break;
              case 'OnDocFormSave':
                  //check for customAction
                  if (isset($_POST['customAction']) && $_POST['customAction'] = "MYADDON") { 
                      //do some stuff here
                  }
                  break;
          }
          return;
          [ed. note: lokamaya last edited this post 13 years, 10 months ago.]
            zaenal.lokamaya
            • 36695
            • 47 Posts
            Thanks for the heads-up. I haven't run into any load/process order issues yet, but I can see the logic in what you're saying and will probably go down this route when I get a second to change the code.
              • 16313
              • 71 Posts
              Thanks for explanation!
              explain please, how can I put combobox to existing User tab e.g. add combobox after Email box on General page?
              I added sample code of prioritypie to OnDocFormPrerender event using $modx->regClientStartupScript($src) and it works, but I don't know how to add only one combo to existing tab.
              here is an example code:
                      items: [
                          {
                              id: 'modx-user-gallery'
                              ,fieldLabel: ('User Gallery')
                              ,xtype: 'modx-combo-gallery'
                              ,width: 200
                          }
                      ]