Ah forms, the bane of a web developer's existence! That and trying to get IE to play nice with your CSS of course. Forms should be easy right? But they're just consistently tricky enough to build from scratch each time and most web developers simply end up keeping a stash of templates handy that they can just reuse.
Well, this tutorial aims to show you how to create reusable forms inside the Orchard CMS back-end made up of the already reusable components built into the core of Orchard. Not only does it take away the pain and drudgery of having to create and test forms in HTML code, but also, should you require, you can dip down to "the metal" in places where you require more control.
We'll cover all of these things here while building a form with the upcoming Orchard Custom Forms module, adding it to the site as both its own landing page, or a widget you would like to plugin to numerous pages, followed by hooking it up with the Orchard Rules module to fire an email out the door based on the rich extensible eventing all built in. Oh, and we'll throw in a bit about permissions as well to show you that security is not an afterthought.
At the time of writing, Orchard v1.4 is the latest release and that is what this solution has been tested on.
First things first
Let's get all the pieces we'll need. I'll assume you have a fully functional site running on Orchard v1.4 or higher. Here's one I baked earlier:
Next, you'll need to download the latest version of the Orchard.CustomForms Module. It's not currently available on the Orchard Gallery since it's slated for the v1.5 release and hasn't been fully tested. I'll update this post once it's available from the gallery.
So there you have it, fair warning that you're embarking on something experimental, but in my experience so far (using it live in production), this has been a very stable experience where most of the moving parts behind this solution, as you'll see, are already baked into Orchard v1.4:
.zip file, you'll see something like the folder on the left below, and you need to copy all of that into a folder called
Orchard.CustomForms you'll create under the
Modules folder in your Orchard project:
A quick glance at the module
Now we're almost ready to go. Fire up the site using WebMatrix or your preferred method, launch it in a browser and sign in to the Admin Dashboard. Under the Modules section on the left, if you filter down on "Forms", you'll see the following.
Let's go ahead and enable that new Custom Forms module, and also enable the Rules module as well if you haven't already since we'll be needing that later on:
If you look under the Forms Admin menu, you'll see there aren't any forms:
And if you try and add a new one, you'll see this list of choices:
Huh?! What's the Content Type thing, and why do I get a choice from them? More importantly, where's my nice big text area I can start putting my form HTML into?
Yep, that's what I thought too - at first. But what I didn't realize is that this module is harnessing one of the most thoroughly tested building blocks of Orchard itself - Content Types! And what can you define in a Content Type? Yes,
Fields of course...as many as you want!
A nice separation of concerns if you like, where the management of fields and data is abstracted away to where it belongs - the already rich Content Type system underpinning the very core of the framework. And the Custom Forms module does what it is supposed to do - presenting Content Types in page or widget shapes to be filled out by your users and enabling the capture of said data.
No more, and no less.
Adding the content type
So lets head over to the Admin Content menu first and create a new Content Type for our form to use:
Next you'll be asked if you want to add any parts to this. I suspect that there may be use cases for this in some advanced tinkering, but for the general purpose, there's no need to do anything here. Our form will consist purely of
Fields for now, and you can get clever with
Parts some other time
Notice that the Content Type will automatically be set to Creatable and Draftable, the former not being very useful since we won't be filling out the form in the Admin UI, and the second would only be needed if you wanted some kind of workflow where forms your users submitted needed to go through some kind of approval process before being published.
If say, for example, you had some freelance workers or perhaps fresh graduates filling in data on your site that needed a second pair of eyes before affecting content, then setting it as draftable could help you with that. I took both options off for this particular form.
So lets go ahead and add some fields. The field type selection will have any field type that is already available in Orchard. If any new ones are added in future, or if you create your own field types, then those will be available here too.
I went ahead and created 4 fields for my subscriber form. Name and Email are
Input fields, Subscribe to Newsletter is
Boolean, and Message is of type
You can probably guess what most of these translate into with regards to HTML, but they each come with their own little surprises. The
Input field comes built in with a number of pattern, validation and usability helpers. You can validate it against some common known patterns or define your own regex, as well as the usual length and required limitations.
Watermarks, Custom CSS and Help Text make it really easy for someone to fill out the form with a minimum of fuss, but what's more important, is that you, as a developer, or even one of your customers who might create forms themselves, don't forget this stuff, which happens all too often when trying to get the business of forms out of the way quickly.
Lets face it, templates or no, it can be a real pain in the butt rolling it from scratch each time.
For Booleans, you get a choice of Selection modes including Checkbox, Radio Buttons or Dropdown and you can also add a Neutral (Maybe) option which is useful in some cases.
Text fields are different to Input fields in a number of ways. Firstly, Input fields can only be single line entry inputs and that is the same for the "Default flavor" for Text Fields. But Text fields can also be made into plain multi-line TextAreas or even fully fledged HTML editors utilizing the same HTML editor that Orchard uses in the Admin. Text fields don't, however, get any of the validation benefits that come with Input fields other than being made "Required".
Go ahead and fill in all the extra bits for your forms fields to make sure they comply with your needs, and then it's off to the Forms section once again to add our form to the site.
As an aside, if you're working outside of Orchard CMS on another .Net framework, then the Html Tags Library from the Fubu Project is an incredibly awesome way of standardising your HTML Forms (and other tags) using code and unit tests to make sure you're consistent.
It means that when you've done it once, you've done it a thousand times. It's not tied to FubuMVC specifically, it's stand-alone and the nice thing is, it can be used in any framework that spits out HTML including ASP.NET MVC or Nancy for example.
Creating the form instance
Now that we've defined our content type we can go and create a new form. Here's one I prepared earlier:
Now it's important to note that by creating a new form this way, you are dedicating an entire page (URL) to it, so the form will stand on its own alongside any widgets perhaps that are on all your pages, but nothing else. This form is not "embedded" anywhere yet as a self-contained widget.
Here's what the form looks like on my example site:
What the hell?! That's gotta be the ugliest form I've ever seen! Well, that may be true, but it's nothing a little CSS can't sort out, and let's be honest here, you'd get the same result if you just wrote the form HTML yourself.
Here's the same form after I fixed it up with a little CSS help:
Well, ok, maybe it's still ugly, but you get the point, you're free make it look just the way you want once you've got the basics down.
Adjusting the placement
One thing you may be wondering about is how to go about adjusting the order in which these fields appear on the page. Well, as you may or may not know, Orchard has a pretty powerful placement system in effect, and I highly recommend you read up about it. It's an elegantly simple solution.
Let's say I wanted the "Subscribe to Newsletter" checkbox rendered above the large Message text area instead. Well, first I need to find out what the placement currently looks like. So go ahead and install and enable the
Designer Tools Module which you can get from the Orchard Gallery if you don't already have it.
textarea form field and see the current placement details:
As you can see, the text area editor is placed at position 2.5, whereas the boolean field editor is placed at position 2.6. So we want the text editor type to appear lower down than 2.6. For that you can go into your theme folder in Orchard and crack open the
Placement.info text file and all you need to do is put something like this in:
<Match ContentType="SubscriberForm"> <Place Fields_Common_Text_Edit="Content:2.10" /> </Match>
There are of course many ways to solve this. In my case I'm targeting my specific new Content Type, so it's pretty certain that this placement won't mess with any other forms I may have created, but feel free to make the placement as broad or specific as you like once you've learned how it works...it really is a very powerful mechanism!
This is what the placement looks like now on my form:
What about widgets?
Sometimes you don't want an entire page dedicated to a form, or sometimes the form is really tiny, or you'd like to include it on multiple pages as a widget, like for example a voting poll or a couple of quick survey questions in the sidebar.
Well, you'll be happy to know that you can create a custom form widget and point to the same Content Type we created earlier via the usual Widgets Admin area. Here I've added my form to the home page for example:
Wanna see something cool?! I thought so. As a result of setting up my field validation requirements in the Content Type, the validations automatically flow through to the UI without any further set up required by you, or your hypothetical clever form creating customer.
Instant feedback, without a return trip to the server. Slick...isn't it?!
At the moment, only certain authenticated users can submit this form. If an anonymous user attempts it, they'll be taken to the login screen. This is a good default to have for obvious safety reasons, but in order to allow anonymous users to submit freely, we can open the Admin Users section, click the Roles tab and edit the Anonymous user role.
In there, further down the screen, you'll see this little guy:
And voilà! Anonymous users can now submit our form and you're ready to get spammed from here to kingdom come!
:D That is, unless you add some reCaptcha of course...
Keeping spam to a minimum without requiring visitors to login is pretty crucial in this day and age. Luckily it's pretty easy to enable one of the most effective combatants of spam on the web today. In order to add reCaptcha to your form, we'll go back to the Content Type we created.
Remember I talked earlier about
Parts coming in to play with forms? Well, this just so happens to be one of those use cases.
Go ahead an add the reCaptcha Part to your Content Type. Another one you can consider is adding the "Submission Limit" part which allows you set set the maximum number of times a user can submit the form within a certain time frame:
Fill in your details and you're ready to rock! Check it out, a submitted reCaptcha enabled form with a nice message displayed afterwards:
Email is just a Rule
I know that many might think that being able to email the results of a form submission belongs with the custom forms module, but in truth, it shouldn't, and here's why:
This basically comes back to the concept of Separation of Concerns again where the job of the custom forms module is to manage the data related to a form submission, nothing more, nothing less. If you add email capabilities to custom forms, then where does its responsibility stop?
Next you'll be adding all sorts of workflow like archiving perhaps or SMS messaging for example, none of which apply to every kind of form, and all of which bloat the module and distract it from its core job - capturing form submissions.
Persistence of that data is key for preservation, but emailing it off somewhere is a job that belongs somewhere else - and in Orchard, that slots in nicely with the Rules module.
Basically, the rule you set up will allow Orchard to react to the event of a form submission by listening for it, and performing one or more appropriate actions, be that an email, or even an SMS message.
Setting up a new Rule is pretty easy, and if you follow the steps, you'll end up with a rule that looks a little something like this. One thing to note is that you'll need to have installed the
Messaging and the
Email Messaging modules to have the Send and e-mail option available in the Actions:
Another built in feature that we are using when sending an email is Orchard Tokens for parametrizing the email subject and body itself. This can allow you to send a very personalized email back to the person who subscribed if you like, among about a billion other use cases.
Here's the one I set up for this Rule:
I suggest reading up about Orchard Tokens - they're incredibly powerful and allow you to create impossibly flexible actions in rules. Enjoy!
I think, if I'm not mistaken, that about covers it in excruciating detail. I know many people complain about missing documentation on OSS projects in general, but from what I've seen, the Orchard Project has some of the best work in that regard.
I hope this goes some way towards helping anyone who wants to explore this awesome feature and this even awesomer framework, and if you feel like a part of this article could be clearer, or I've left out something crucial, please go ahead and drop me a message in the comments below - I'd be happy to hear from you.
Other than that, have fun playing with this feature, and if folks find this useful, I might have another couple of Orchard topics to add in the near future. You can let me know if you have any requests too!
Until next time