If you've ever created a MuraFW1 plugin for Mura CMS (which this article assumes by the way!), you may have wondered how to go about creating dynamic Content Display Objects. Doing so would enable an end-user to edit a page, go to the Content Objects tab, select Plugins from the Available Content Objects dropdown, select your plugin, then select your "dynamic display object" which would then fire off and return yet form field containing the dynamic list of options available to be assigned to the desired content display region.
Still with me? Great!
Ultimately, there's three main parts to this:
1. Create the display method, i.e., myDisplay
2. Then create an "OptionsRender" display method which follows the naming convention of myDisplayOptionsRender
3. Finally, we'll add the basic display method (i.e., myDisplay) to the config.xml.cfm's list of available displayObjects
1. Create The Display Method
In the pluginEventHandler.cfc, we can add our basic display method. Ultimately, we should eventually expect a JSON formatted variable to be passed in via $.event('params'). Obviously, we'll need to deserialize the JSON, and once we do that, we can do whatever we like with it. An easy way to pass this information over to FW/1 is to stuff any desired variables into the URL scope ... and then call the typical renderApp() method and let FW/1 take over from there. Check out our simple example below which is expecting to find "whateverID" to be in the unpacked params:
<cffunction name="dspWhatever" output="false" returntype="any">
<cfargument name="$" hint="mura scope" />
<cfscript>
var local = {};
// grab everything that's been passed in from OptionsRender() and unpack the JSON option values that were saved
local.params = DeserializeJSON($.event('params'));
// stuff selected WhateverID into the url scope so that fw1 will pick it up
if ( StructKeyExists(local.params, 'whateverid') ) {
url.whateverid = local.params.whateverid;
};
// something went wrong ... so let's not bomb everything
if ( not StructKeyExists(url, 'whateverid') ) {
return '';
} else {
return renderApp($,'public:main.default');
};
</cfscript>
</cffunction>
2. Create An "OptionsRender" Method
Now for the magical part! Whatever you named your displayMethod, you simply append "OptionsRender" to the end of it. So if you have dspWidgets, then you would have dspWidgetsOptionsRender as an available method. In the example below, I'm creating a simple recordset which we'll then loop over to output the options and dynamically generate the option value which is a tilde (~) separated list where the last item in the list is a JSON formatted list of params...yes, the very same params our display method in step one is expecting to find!
<cffunction name="dspWhateverOptionsRender" output="false" returntype="any">
<cfargument name="$" />
<cfscript>
var local = {};
// this recordset could come from anywhere ... doesn't even have to be a recordset, could be anything that contains data that you want to grab options from
local.rs = QueryNew('WhateverID,WhateverTitle,WhateverField', 'VarChar,VarChar,VarChar');
QueryAddRow(local.rs, 1);
QuerySetCell(local.rs,'WhateverID', 'anyid-1', 1);
QuerySetCell(local.rs,'WhateverTitle', 'My Awesome Title', 1);
QuerySetCell(local.rs, 'WhateverField', 'Hi Ho Cherry-O', 1);
QueryAddRow(local.rs, 1);
QuerySetCell(local.rs, 'WhateverID', 'anyid-2', 2);
QuerySetCell(local.rs, 'WhateverTitle', 'Another Great Title', 2);
QuerySetCell(local.rs, 'WhateverField', 'Knick Knack Paddy Whack', 2);
</cfscript>
<cfsavecontent variable="local.str">
<cfif local.rs.recordcount>
<select name="availableObjects" id="availableObjects" class="dropdown">
<!--- we're going to pack everything up into a tilde (~) separated list where the last item in the is a JSON formatted list of params to be passed over to the display method --->
<cfoutput query="local.rs">
<option value="plugin~#HTMLEditFormat(Replace(WhateverTitle,'~','','ALL'))#~#$.event('objectid')#~{'whateverid':'#WhateverID#','anotherfield':'#WhateverField#'}">
#HTMLEditFormat(WhateverTitle)#
</option>
</cfoutput>
</select>
<cfelse>
<p><em>Please create some Whatevers first.</em></p>
</cfif>
</cfsavecontent>
<cfreturn local.str />
</cffunction>
3. Add The Rendering Method To config.xml.cfm
The final step in all this is to add your basic displayMethod to your config.xml.cfm file so that it will be registered with Mura CMS. Once it is, then we should expect to see it show up in the Content Objects tab when someone selects our plugin.
<displayobjects location="global">
<displayobject name="Display Whatever" displaymethod="dspWhatever" component="pluginEventHandler" persist="false" />
</displayobjects>
That's it! Hopefully this helps anyone else who is creating FW/1 plugins for Mura CMS.
Cheers!