Live AJAXy web 2.0 inline previews are great when writing blog entries, but what if you want to see a preview of your content in its presentational context? Like, as if it were real content on your site. You can save it to the database in a previews table, I guess. Or you can, straight from your data entry form, submit to a popup of your actual display action. Where your display action normally does a Story.find(params[:id]), have it build an object from the form parameters. What follows is very basic, not simply restful, and not very DRY—but we’re here to illustrate a concept. So stick with it.
First, here’s our StoriesController code. It faces the public and displays a story.
class StoriesController < ApplicationController def preview @story = Story.new(params[:story]) render :action => :show end def show @story = Story.find(params[:id]) end end
Notice the preview action: it’s grabbing its own version of @story based on the story form post’d to it. It’s then rendering the show action. For all show.rhtml knows, it’s rendering a real live story!
Now in a real app, you’d probably want to lock preview behind some sort of authentication check. We don’t want just anyone submitting arbitrary data to our site, now, do we?
The next thing we’re going to do is create our Story data entry form. This probably lives somewhere like Admin::StoriesController under the new action.
<h1>New story</h1> <%= error_messages_for 'story' %> <% form_for :story, @story do |f| %> <p><label for="story_title">Title</label><br/> <%= f.text_field :title %></p> <p><label for="story_body">Body</label><br/> <%= f.text_area :body %></p> <p><label for="story_created_at">Created at</label><br/> <%= f.datetime_select :created_at %></p> <%= submit_to_popup "Preview", :url => { :controller => '/stories', :action => 'preview' } %> <%= submit_tag "Create" %> <% end %>
Do you see it? submit_to_popup. We’re giving it a name and passing it a :url hash just like we would with many other Rails helpers. What we’re going to get is a form button with a label of Preview that, when clicked, submits its form data to a popup window.
To get this all working drop this bit of code into a helper, like ApplicationHelper:
def submit_to_popup(label, options = {}) form_var = options[:form_id] ? "$('#{options[:form_id]}')" : 'this.form' url = case options[:url] when String then options[:url] when Hash then url_for options[:url] else url_for end button_to_function label, "var form=#{form_var};form.action='#{url}';form.target='_blank';form.submit();form.action='#{url_for}';form.target='';return false" end
Here’s the normal form:
And here we are with a successful preview:
Just to let you know, you can submit any form on the page by passing the :id key to submit_to_popup. You can also pass :url a straight URL, ala http://www.pepsicola.com, if you’re rather do that instead.
Real cool.
submit_to_popup is worthless
come on … its not ‘worthless’ – this is a fairly common action – incl. on any content submission (comments, articles etc.)
Hey that’s pretty cool. I like the preview action in the controller too. Neat stuff as always.
Here’s a slight modification to the preview action, which layers the form field data over existing data from the db—useful in the case that the form doesn’t contain all the fields/associations that are shown in the view:
It works like a charm!,
Thanks
Not a big fan of popups. Also, with the way AJAX is going these days there’s no reason you can’t let people edit they’re content exactly as it would look in the form itself (dojo editor for example).
Yeah, yeah, I know us nerds love text based stuff like textile, but your average user wants to write content like they do in Microsoft Word.
Granted, Dojo isn’t all there yet. It’s got some hangouts (ours doesn’t work in safari atm in boompa) but I really things writely style progs are gonna show up more and more in our form use.
This is not for end users, it’s for administrators entering content—like bloggers making a new post. Check out WordPress’ admin interface. It’s nice to see your post WYSIWYG in a little div, but it’s also nice to see your post as if it was an actual post on your site. In context.
If you don’t want to do a popup, you could easily hack together an iframe/thickbox implementation with code already out there (like the Redbox plugin.)
Chime in.