Reputation: 1985
Kentico 12 only supports forms using the "Form" page-builder widget out of the box.
Can anyone provide examples of how one might utilise BizForms on an MVC _Layout.cshtml or in pages that do not use the page builder?
Acceptance criteria:
Upvotes: 2
Views: 1315
Reputation: 18225
The OP posted a blog about how to make this work.
The solution requires using some of Kentico's internal APIs for Form Builder rendering with Form Widgets and putting that code into a Controller action.
var formInfo = BizFormInfoProvider
.GetBizFormInfo(formName, SiteContext.CurrentSiteName);
string className = DataClassInfoProvider
.GetClassName(formInfo.FormClassID);
var existingBizFormItem = className is null
? null
: BizFormItemProvider
.GetItems(className)?.GetExistingItemForContact(
formInfo, contactContext.ContactGuid);
var formComponents = formProvider
.GetFormComponents(formInfo)
.GetDisplayedComponents(
ContactManagementContext.CurrentContact,
formInfo, existingBizFormItem, visibilityEvaluator);
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
TypeNameHandling = TypeNameHandling.Auto,
StringEscapeHandling = StringEscapeHandling.EscapeHtml
};
var formConfiguration = JsonConvert.DeserializeObject<FormBuilderConfiguration>(
formInfo.FormBuilderLayout, settings);
return new FormWidgetViewModel
{
DisplayValidationErrors = true,
FormComponents = formComponents.ToList(),
FormConfiguration = formConfiguration,
FormName = formName,
FormPrefix = Guid.NewGuid().ToString(),
IsFormSubmittable = true,
SiteForms = new List<SelectListItem>(),
SubmitButtonImage = formInfo.FormSubmitButtonImage,
SubmitButtonText = string.IsNullOrEmpty(formInfo.FormSubmitButtonText)
? ResHelper.GetString("general.submit")
: ResHelper.LocalizeString(formInfo.FormSubmitButtonText)
};
I took that idea and wrote a follow up post, Kentico EMS: MVC Widget Experiments Part 3 - Rendering Form Builder Forms Without Widgets, which shows we can also use Kentico's pre-built Form Widget view code to also get the expected rendering and form submission functionality.
<!-- ~/Views/Form/Form.cshtml -->
@using Kentico.Forms.Web.Mvc;
@using Kentico.Forms.Web.Mvc.Widgets;
@using Kentico.Forms.Web.Mvc.Widgets.Internal
@model FormWidgetViewModel
@{
var config = FormWidgetRenderingConfiguration.Default;
// @Html.Kentico().FormSubmitButton(Model) requires
// this ViewData value to be populated. Normally it
// executes as part of the Widget rendering, but since
// we aren't rendering a Widget, we have to do it manually
ViewData.AddFormWidgetRenderingConfiguration(config);
}
@using (Html.Kentico().BeginForm(Model))
{
@Html.Kentico().FormFields(Model)
@Html.Kentico().FormSubmitButton(Model)
}
Upvotes: 2
Reputation: 198
The Form widget is rendered using a combination of the following view structure and the view model FormWidgetViewModel
:
using (Ajax.Kentico().BeginForm( ... ))
{
@Html.AntiForgeryToken()
@Html.Kentico().FormFields(Model.FormComponents, Model.FormConfiguration, FormFieldRenderingConfiguration.Widget)
// Render Model.SubmitButtonImage using @Html.Kentico().ImageInput( ... )
// Or render a plain <input> using Model.SubmitButtonText
}
If you have the BizFormInfo
object for the form, it is needed for the following properties:
new FormWidgetViewModel
{
FormName = formInfo.FormName,
FormConfiguration = IFormBuilderConfigurationRetriever.Retrieve(formInfo),
FormComponents = IFormProvider.GetFormComponents(formInfo).GetDisplayedComponents( ... ),
FormPrefix = // This may be optional outside of the Page Builder context,
SubmitButtonText = formInfo.FormSubmitButtonText,
SubmitButtonImage = formInfo.FormSubmitButtonImage
}
Inside Ajax.Kentico().BeginForm
you can pass in the controller and action handling the form.
Use methods in IFormProvider
to update or add the form submission and to send emails.
Update (see comments):
IFormBuilderConfigurationRetriever
is marked internal
, so it is not directly accessible. Its implementation in turn uses IFormBuilderConfigurationSerializer
to deserialize formInfo.FormBuilderLayout
. That interface is also marked internal
. Further, the implementation of that interface uses the internal
FormBuilderTypesBinder
.
This means that there is no API available to retrieve Model.FormConfiguration
. As of Kentico 12.0.16, you would need to recreate the internal functionality. The basic implementation is like this:
JsonConvert.DeserializeObject<FormBuilderConfiguration>(formInfo.FormBuilderLayout, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
TypeNameHandling = TypeNameHandling.Auto,
SerializationBinder = // Set to the internal FormBuilderTypesBinder, which validates only known form builder types
StringEscapeHandling = StringEscapeHandling.EscapeHtml
});
Upvotes: 1
Reputation: 1418
You can take a look at the Kentico.Forms.Web.Mvc.Widgets
namespace in your MVC project (it should be included by default).
In there is a KenticoFormWidgetController
controller class which renders form partials and accepts form submissions. You could possibly use the Index route of that controller to render a partial of your form, however it is unknown to me how exactly the route looks.
If you have source code access to Kentico you could check the internals of it by yourself.
Upvotes: 0
Reputation: 1549
Hades, You might user Forms API (https://docs.kentico.com/api12/content-management/form-data) to save/access form data and implement completely custom layout for it. Hope that helps!
Upvotes: 0