How to Create Dynamic Content Display Objects in Mura CMS with MuraFW1 Plugins

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!

Comments

Nice post steve. Very similar to Grant Shepery post here that i have used to create a custom image gallery.

http://www.grantshepert.com/post.cfm/advanced-plug...

But your post is an excellent addition.
# Posted By jbuda | 8/31/11 8:43 AM
@jbuda,

yeah, he had a great post on this topic. one point i wanted to illustrate is that it's possible to do this without actually having to modify the MuraFW1 plugin's renderApp() method ... it's very easy to just stuff anything the plugin is already listening for into the url scope, etc. so that fw1 will just pick it up and respond if necessary.

cheers!
# Posted By Steve Withington | 8/31/11 9:01 AM
Great Post! Any thoughts on how you'd pass in a list of Content Collections, so that the user can simply choose the content collection they'd want to use for the specific plugin? I have a slider plugin that just takes an ID to get the collection to pass into, and it would be ideal if i can have that ID be automated a bit, so that the user could pick, and put that slider on many different pages, using many different content collections.

I'll poke around your site and Grant's more to find the answer to my own question, but if you can i'd appreciate any suggested approach.

All the best,
David
# Posted By David Panzarella | 8/31/11 10:53 AM
Great post, thanks!
# Posted By Sean Walsh | 8/31/11 11:03 AM
Iam not talking about dynamic display object here- rather my issue is how to create a simple displayobject on our MURAFW1 plugin.

I want to call public:dept.list from the below displayobject
<displayobject name="depList" displaymethod="renderApp(action='public:dept.list')" component="pluginEventHandler" persist="false" />
But I get only errors:

"    Ensure that the method is defined, and that it is spelled correctly.
Message    The method renderApp(action='public:dept.list') was not found in component D:\Zend\Apache2\htdocs\learnMura.loc\plugins\muraFW1\pluginEventHandler.cfc."

Actually list method on dept controller exists.
# Posted By Shimju David | 4/4/12 10:20 PM
@Shimju,

Sorry for the delay, I was on vacation and had limited access to internet.

Anyway, in your case, simply create a method in the pluginEventHandler.cfc called something like "dspDepList" which returns renderApp(action='public:dep.list')

For example:
<displayobject name="depList" displaymethod="dspDepList" component="pluginEventHandler" persist="false" />

Then,
<cffunction name="dspDepList">
<cfreturn renderApp(action='public:dep.list') />
</cffunction>

Hope that helps!
# Posted By Steve Withington | 4/11/12 9:22 AM

© 2024, Stephen J. Withington, Jr.  |  Hosted by Hostek.com

Creative Commons License   |   This work is licensed under a Creative Commons Attribution 3.0 Unported License.