Xperience by Kentico has a very powerful form builder that allows you to dynamically build forms to collect data from your website visitors. This post will take a deeper look into how we can customize the output of those forms since we're not able to use the custom layout option.
At Kehren Development, we've made the move away from Portal Engine development to now building 100% of our new Xperience sites using MVC. As we made this migration to MVC, we've found quite a few areas that we love and some that we really miss in the Portal Engine development method. One thing we initially missed but have very quickly gotten over is the ability to customize the output of a simple "contact us" form. Let's take a deeper look into some pitfalls and some advancements we've discovered.
The Problem
Creating forms on a website to collect data isn't going away anytime soon. Being able to style those forms the way you want, consistently, on a site shouldn't require a developer when a new form is created either. Using Xperience's Portal Engine development method we were able to create a custom form layout and define quickly how the form will look on the public site.
With the migration to MVC, the alternative forms have since went away. One downfall with this approach is it required you to add these custom layouts for each new form you created. There was no global way to style these elements without digging deep into the custom output HTML and applying some crazy CSS.
While the Xperience dev team has done a great job removing a lot of the bloated HTML from the form controls, there are still some areas where they need some help. Enter the Kentico.Forms.Web.Mvc
namespace.
A Solution
One of the first sites we did we created in MVC we made a custom form without using the out of the box Form Widget simply because we couldn't apply the custom HTML we needed to get the form to look like the client wanted. Little did we know there were already API's in place to handle this. In the Xperience documentation you'll find a lot of the specifics around what you can do to customize your forms, but below, I'll share with you how to do a few simple things we find we do on every MVC site we're creating.
The best part about all of the following code I'm going to show you is it will perform these formatting actions for EVERY form you place on your site. So if you have a very form heavy website, you implment this one time and it works for every form you add! You can also make this portable too so it will work in other projects, but that's another post.
A couple things to get started. First you'll need to create a class to handle your custom events. I've called it FormFieldMarkupInjection.cs and placed it under the /Lib/FormEvents folder in my project.
This is the stub code, we'll add the methods to it later in the post.
using System;
using Kentico.Forms.Web.Mvc;
namespace KehrenDev.Lib.FormEvents
{
public class FormFieldMarkupInjection
{
public static void RegisterEventHandlers()
{
// Contextually customizes the markup of rendered form fields
}
}
}
Next we need to ensure this handler is called upon MVC application startup. So in the Global.asax.cs file be sure to call this handler in the Application_Start() event:
KehrenDev.Lib.FormEvents.FormFieldMarkupInjection.RegisterEventHandlers();
Now we're going to create a function to do the custom work in the FormFieldMarkupInjection class.
// Contextually customizes the markup of rendered form fields
FormFieldRenderingConfiguration.GetConfiguration.Execute += InjectMarkupIntoKenticoComponents;
private static void InjectMarkupIntoKenticoComponents(object sender, GetFormFieldRenderingConfigurationEventArgs e)
{
// do the work here
}
Now let's get into the meat and potatoes of this post! Here are a few scenarios we've come across.
- You need a specific wrapper <div> tag and css class around the <form> element.
- Adding a css class directly to the <form> element.
- The client has a specific style for buttons on forms which is not replicated anywhere else on the site.
- Adding accessibility attributes to required fields.
#1
Adding a wrapper element and css class on the <form> element is the most popular request. If you're using the out of the box widget, you'd have to count on the editor to add this or you'd have to customize the widget quite a bit to get this to work. Another option is to build your own. So by writing a few simple lines of code you can inject this element and css pretty easy.
// Elements wrapping the Form element
FormWrapperConfiguration = new FormWrapperRenderingConfiguration
{
ElementName = "div",
HtmlAttributes = { { "class", "form-widget-form" } },
// Adds an additional div element wrapper
ChildConfiguration = new ElementRenderingConfiguration
{
ElementName = "div"
}
}
The code above will add a wrapping <div> tag around the <form> tag with the "form-wrapper" css class attribute set.
#2
Adding a css class directly to the <form> element is by a very common request as well. Take a look here how you can do this.
FormWidgetRenderingConfiguration.Default = new FormWidgetRenderingConfiguration
{
// Form element HTML attributes
FormHtmlAttributes = { { "class", "form-class" } }
}
#3
Buttons. Who's had a site where buttons follow a standard bootstrap or foundation color? Me either. Adding a css class to a button may not be as easy as one thinks in Xperience, but the following code will allow you to set that with ease on every form.
FormWidgetRenderingConfiguration.Default = new FormWidgetRenderingConfiguration
{
// Submit buttom HTML attributes
SubmitButtonHtmlAttributes = { { "class", "btn btn-lg btn-secondary" } }
}
#4
Accessibility attributes are more important than ever on your website. Here's an example of how to simply add the "required" pieces to a required field.
if (e.FormComponent.BaseProperties.Required)
{
// Adds the 'aria-required' and 'required' attributes to the component's 'input' element
e.Configuration.EditorHtmlAttributes["aria-required"] = "true";
e.Configuration.EditorHtmlAttributes["required"] = "";
// Appends an asterisk to the component's 'Label' element. Since the class attribute is fairly
// common, checks if the key is already present and inserts or appends the key accordingly.
if (e.Configuration.LabelHtmlAttributes.ContainsKey("class"))
{
e.Configuration.LabelHtmlAttributes["class"] += " required-field-red-star";
}
else
{
e.Configuration.LabelHtmlAttributes["class"] = "required-field-red-star";
}
}
Summary
There are many other opportunities in which you'd want to customize your form and it's attributes. These are simply a few of our most common requirements. Take a look at the API and the examples Kentico provides to get you a bit more help. If you have questions more about this, feel free to comment below.
Full Source download