One of the things I’m writing at the moment is a fairly complex bespoke content management system. I’ve done a fair few CMSes in my time, but most of them have had relatively simple back ends – you know the type, where you’ve got a separate ‘admin’ section, which in CF terms is often a completely different application; this is usually for authentication’s sake (let’s face it, it’s fairly easy to secure an entire application.cfc) and to keep it relatively contained in a single folder.
As I’ve been playing around with CfWheels of late, I thought I’d force myself to use it with this project, as for me, that’s usually the best way to learn something – plus I always had the ‘get out’ clause of being able to override internal wheels behaviour if needed. Wheels instantly throws you into a different mindset when it comes to CMS-like apps; as there are various conventions like MVC and ORM already in place, it makes sense to approach everything from that ‘wheels’ point of view.
As building forms is so insanely easy in wheels (see the form helpers), I very quickly got to the point where I started to crave a little more interaction; especially when starting to deal with many to many relationships, and how to update those. But my main objective was to break out of the ‘separate-page-in-a-different-application-to-update’ mindset.
Enter jQuery & colorbox based forms. Having not really played around with jQuery that much (I know, I know) I’ve been pretty shocked about how quickly I managed to pull together some proof of concept forms. Add something like colorbox into the mix, and suddenly you’ve got instant editing ability from any page in your application, without going to have to find the entry in the admin section.
I’m going to try my best to explain where I’ve got to, with the usual caveats – there’s almost always a better way to do this, and I’ve probably just not come across it yet – so comments welcomed..
I’m going to assume you have a basic wheels framework in place, complete with your datasource. For this example, I’m just going to concentrate on one controller and a couple of views.
Starting up – the layout file
The first thing is to include the necessary JS & CSS files, so in my layout.cfm file I’ve got
The Main View page
We need a page view which will output our page object, and provide our edit link: so in /views/pages/view.cfm you might have something like this:
<cfparam name="page"> <cfoutput><p class="admin-links"> #linkTo(text="Edit This Page", class="colorbox", action="edit", key=page.id)# </p> #page.content# </cfoutput>
Next, we need a form:
In my /views/pages folder, I’ve got a ‘partial’ called _form.cfm, which is basically a view designed to be called without layout.
#startFormTag(action="update")# #hiddenField(objectName="page", property="id")# #textArea(objectName="page", property="content")# #submitTag()# #endFormTag()#
Nothing too unusual there, move along..
In this file, i’ve got 3 functions: A view, edit and update function. The edit function is fired when the form is loaded, and the update function is fired on the submission of the form.
<cffunction name="view"> <cfset page = model("page").findAllBySESURL(value=params.title)> </cffunction> <cffunction name="edit"> <cfset page = model("page").findByKey(key=params.key)> <cfset renderPartial("pageform")> </cffunction> <cffunction name="update"> <cfset page = model("page").findByKey(params.page.id)> <cfset page.update(params.page)> <cfif page.hasErrors()> <cfset flashInsert(error="Page Content couldn't update.")> <cfset redirectTo(back=true)> <cfelse> <cfset flashInsert(success="Page Content updated successfully.")> <cfset redirectTo(back=true)> </cfif> </cffunction>
Note the renderPartial(“form”) line. This makes wheels look for a “_form.cfm” file in my /views/pages/ folder. The other bit of note is ‘redirectTo(back=true)’ – this closes the modal window and updates our initial page.
Tie it all together:
This tells colorbox to open any link with a class of .colorbox.
So really, it’s three simple things to remember:
- opening the form via colorbox requires a class/id in the link (at least, that’s one way of doing it, there are many others)
- Using partials in modal windows means you don’t have to have the layout, and you can reuse that form from anywhere (you could also use renderPage(layout=false))
- Using redirectTo(back=true) does refresh the page, but the most important thing is, you’ve not really left it due to the overlay.