Introduction
Welcome to the Form.X for XMod Pro documentation. Form.X is a powerful control that allows you to embed forms within an XMod Pro template. This allows you to add and edit data without a page refresh, create contact forms and more!
Prerequisites
Form.X requires the following:
- DNN v7.2.0+
- XMod Pro v4.7.3+
- .NET v4.0+
Installation
Navigate to your extensions page and install Reflect_XModPro_FormX_##.##.##.Install.zip as you would any typical module.
Setup
Example setup
<xmod:Register TagPrefix="fx"
Namespace="Reflect.XModPro.Templates.FormX"
Assembly="Reflect.XModPro.Templates.FormX" />
<xmod:Template Id="ContactUs" Ajax="True">
<DetailDataSource CommandText="SELECT 1" />
<DetailTemplate>
<fx:FormX Mode="Add">
<addform>
<div class="form">
<div class="form-group">
<label for="Firstname">First name</label>
<Textbox Id="Firstname" Datafield="Firstname" Datatype="String" CssClass="form-control" />
<Validate Type="Required" Target="Firstname" Text="* Required" />
</div>
<div class="form-group">
<label for="Lastname">Last name</label>
<Textbox Id="Lastname" Datafield="Lastname" Datatype="String" CssClass="form-control" />
<Validate Type="Required" Target="Lastname" Text="* Required" />
</div>
<div class="form-group">
<label for="Comments">Comments</label>
<Textarea Id="Comments" Datafield="Comments" CssClass="form-control" />
<Validate Type="Required" Target="Comments" Text="* Required" />
</div>
<AddButton Text="Send Message" CssClass="btn btn-primary" />
</div>
<Email To="change@me.com"
From="change@me.com"
Subject="Message from {{Firstname}}" Format="Text">
Hello. You got a message:
Name: {{Firstname}}
Last Name: {{Lastname}}
Comments: {{Comments}}
</Email>
</addform>
<addsuccesstemplate>
<div class="alert alert-success">
<p>
Thanks, {{Firstname}}! We'll get back to you ASAP!
</p>
<ContinueButton Text="Continue" CssClass="btn btn-default" />
</div>
</addsuccesstemplate>
</fx:FormX>
</DetailTemplate>
</xmod:Template>
Form.X operates within an <xmod:Template>
tag. You must register the control within your XMod Pro template file. See the example code on the right.
Create a new template. We will use a simple contact form example to get you started. The different token syntax you will see will be explained
in just a bit!
Views
<fx:FormX AddRoles="Role1,Role2" EditRoles="Role1,Role2" Mode="Template|Add|Edit">
<template>...</template>
<addform>...</addform>
<addsuccesstemplate>...</addsuccesstemplate>
<editform>...</editform>
<editsuccesstemplate>...</editsuccesstemplate>
</fx:FormX>
Form.X contains the following views:
- Template
- AddForm
- AddSuccessTemplate
- EditForm
- EditSuccessTemplate
The naming of views should look familiar to you. A typical workflow would look like this:
- Load whatever is in the
<Template>
view by default - If
<fx:AddButton>
is clicked, load the<AddForm>
. - Upon form submission, load the
<AddSuccessTemplate>
if found, or back to the<Template>
if not. - If
<fx:EditButton>
is clicked, load the<EditForm>
. - Upon form submission, load the
<EditSuccessTemplate>
if found, or back to the<Template>
if not.
Simple, right?
You can override the default view (i.e. <Template>
) by setting the Mode property. This is good for contact forms.
You can also, similar to XMod Pro templates, specify DNN Security roles for <fx:AddButton>
and <fx:EditButton>
.
As you would expect, this defaults to Administrators and Super Users.
See the example on the right.
<Template>
The <Template>
tag is nested within the parent <fx:FormX>
control.
Unless otherwise specified (i.e. <fx:FormX Mode="Add">
) this will be the default view.
<AddForm>
<fx:FormX Mode="Add">
<addform Clientname="string">
<SelectCommand .../>
<SubmitCommand .../>
<ControlDataSource .../>
... HTML and Form Controls
</addform>
<addsuccesstemplate>...</addsuccesstemplate>
</fx:FormX>
The <AddForm>
tag is nested within the parent <fx:FormX>
control.
This view is triggered from within the <Template>
when a <fx:AddButton>
is clicked.
The <SelectCommand>
works much like XMod Pro's <SelectCommand>
within forms.
The <SubmitCommand>
does as well, with the exception of return parameters, output parameters, and database validation (i.e. <Validate Type="Database" />).
This feature is coming soon!
The ClientName
works much like XMod Pro's ClientName feature on forms. Be sure to provide a unique name (i.e. MyAwesomeForm) for
each instance of the AddForm
. This creates a function so you can access your controls by their ID.
<AddSuccessTemplate>
<fx:FormX Mode="Add">
<addform>
<SelectCommand .../>
<SubmitCommand .../>
<ControlDataSource .../>
... HTML and Form Controls
<AddButton Text="Save" />
</addform>
<addsuccesstemplate>
Congratulations, {{Firstname}}! <ContinueButton Text="Continue" />
</addsuccesstemplate>
</fx:FormX>
The <AddSuccessTemplate>
tag is nested within the parent <fx:FormX>
control.
This view is triggered from within the <AddForm>
when a <AddButton>
is clicked, following successful form submission.
<EditForm>
<fx:FormX>
<template>
HTML and Template Controls...
<fx:EditButton Text="Edit">
<Parameter Name="ProductID" Value='[[ProductID]]' DataType="Int32" />
</fx:EditButton>
</template>
<editform ClientName="string">
<SelectCommand CommandText="SELECT * FROM dbo.Product WHERE ProductID = @ProductID" />
<SubmitCommand .../>
<ControlDataSource .../>
... HTML and Form Controls
</editform>
<editsuccesstemplate>...</editsuccesstemplate>
</fx:FormX>
The <EditForm>
tag is nested within the parent <fx:FormX>
control.
This view is triggered from within the <Template>
when a <fx:EditButton>
is clicked.
The <SelectCommand>
works much like XMod Pro's <SelectCommand>
within forms.
The <SubmitCommand>
does as well, with the exception of return parameters, output parameters, and database validation (i.e. <Validate Type="Database" />).
This feature is coming soon!
The ClientName
works much like XMod Pro's ClientName feature on forms. Be sure to provide a unique name (i.e. MyAwesomeForm) for
each instance of the EditForm
. This creates a function so you can access your controls by their ID.
<EditSuccessTemplate>
<fx:FormX>
<template>
HTML and Template Controls...
<fx:EditButton Text="Edit">
<Parameter Name="ProductID" Value='[[ProductID]]' DataType="Int32" />
</fx:EditButton>
</template>
<editform>
<SelectCommand CommandText="SELECT * FROM dbo.Product WHERE ProductID = @ProductID />
<SubmitCommand .../>
<ControlDataSource .../>
... HTML and Form Controls
<UpdateButton Text="Save" />
</editform>
<editsuccesstemplate>
Congratulations, you updated the product's name to {{ProductName}}!
</editsuccesstemplate>
</fx:FormX>
The <EditSuccessTemplate>
tag is nested within the parent <fx:FormX>
control.
This view is triggered from within the <EditForm>
when a <EditButton>
is clicked, following successful form submission.
Template Controls
<fx:FormX AddRoles="Role1,Role2" EditRoles="Role1,Role2" Mode="Template|Add|Edit">
<template>...</template>
</fx:FormX>
The following controls can be used within the <template>
tag:
<fx:AddButton>
<fx:FormX Mode="Template">
<template>
<fx:AddButton Text="Add Record">
<Parameter ... />
</fx:AddButton>
</template>
<addform>...</addform>
</fx:FormX>
The <fx:AddButton>
control loads the <AddForm>
when clicked. You can optionally pass parameters from your template which
can be retrieved from within your form's <SelectCommand>
.
<fx:EditButton>
<fx:FormX Mode="Template">
<template>
<fx:EditButton Text="Edit Record">
<Parameter Name="ProductID" Value='[[ProductID]]' DataType="Int32" />
</fx:EditButton>
</template>
<editform>
<SelectCommand Commandtext="SELECT * FROM dbo.Product WHERE ProductID = @ProductID" />
... HTML and form controls
</editform>
</fx:FormX>
The <fx:EditButton>
control loads the <EditForm>
when clicked. You can optionally pass parameters from your template which
can be retrieved from within your form's <SelectCommand>
.
Form Controls
<fx:FormX AddRoles="Role1,Role2" EditRoles="Role1,Role2" Mode="Template|Add|Edit">
<addform>...</addform>
<editform>...</editform>
</fx:FormX>
<AddButton>
<AddButton
CssClass="string"
Height="size"
OnClientClick="string"
Style="string"
TabIndex="integer"
Text="string"
ToolTip="string"
Visible="True|False"
Width="size"
<Command ... />
/>
The <AddButton>
control should only be used within the <AddForm>
view.
Take a look at the XMod Pro official documentation on the <CommandButton>
control. In Form.X, the
<AddButton>
supports the nested commands. This allows you to target your other templates by ID.
<CalendarButton>
<CalendarButton
CssClass="string"
Format="date-formatting expression"
Height="size"
Style="string"
TabIndex="integer"
Target="ID of control that will receive the selected date"
Text="string"
ToolTip="string"
Visible="True|False"
Width="size"
/>
<CalendarLink>
<CalendarLink
CssClass="string"
Format="date-formatting expression"
Height="size"
Style="string"
TabIndex="integer"
Target="ID of control that will receive the selected date"
Text="string"
ToolTip="string"
Visible="True|False"
Width="size"
/>
<CalendarImage>
<CalendarImage
CssClass="string"
Format="date-formatting expression"
Height="size"
Style="string"
TabIndex="integer"
Target="ID of control that will receive the selected date"
Text="string"
ToolTip="string"
Visible="True|False"
Width="size"
ImageUrl="url"
/>
<CancelButton>
<CancelButton
CssClass="string"
Height="size"
Style="string"
TabIndex="integer"
Text="string"
ToolTip="string"
Visible="True|False"
Width="size"
/>
<Captcha>
<Captcha
CaptchaChars="string"
CaptchaHeight="size"
CaptchaLength="integer"
CaptchaWidth="size"
CssClass="string"
ErrorMessage="string"
Expiration="integer"
Height="size"
ID="string"
Text="string"
Width="size"
/>
<CheckBox>
<CheckBox
CssClass="string"
DataField="string"
DataType="Boolean"
Height="size"
ID="string"
Nullable="True|False"
Style="string"
TabIndex="integer"
Text="string"
TextAlign="Left|Right"
ToolTip="string"
Visible="True|False"
Width="size"
/>
<CheckBoxList>
<CheckBoxList
AppendDataBoundItems="True|False"
CssClass="string"
DataField="string"
DataSourceID="string"
DataTextField="string"
DataTextFormatString="string"
DataType="string|int32|...."
DataValueField="string"
Height="size"
ID="string"
Nullable="True|False"
RepeatColumns="integer"
RepeatDirection="Horizontal|Vertical"
RepeatLayout="Table|Flow"
SelectedItemsSeparator="string||"
Style="string"
TabIndex="integer"
TextAlign="Left|Right"
ToolTip="string"
Visible="True|False"
Width="size">
<ListItem Value="1">Item1</ListItem>
<ListItem Value="2">Item2</ListItem>
...
</CheckBoxList>
<ContinueButton>
<ContinueButton
CssClass="string"
Height="size"
OnClientClick="string"
Style="string"
Text="string"
ToolTip="string"
Visible="True|False"
Width="size"
/>
<ControlDataSource>
<ControlDataSource
CommandText="string"
CommandType="StoredProcedure"
ConnectionString="string"
Id="string">
Optionally add Parameter tags for any parameters you need to send to the database.
<Parameter Name="string" Value="string" DataType="data type" />
...
</ControlDataSource>
<DateInput>
<DateInput
CssClass="string"
Culture="locale id"
DataField="string"
DataType="datetime|date"
DateOnly="True|False"
Format="date/time formatting expression"
Height="size"
ID="string"
Nullable="True|False"
ReadOnly="True|False"
Style="string"
TabIndex="integer"
ToolTip="string"
Visible="True|False"
Width="size"
/>
<DropDownList>
<DropDownList
AppendDataBoundItems="True|False"
CssClass="string"
DataField="string"
DataSourceID="string"
DataTextField="string"
DataType="string|int32|...."
DataValueField="string"
Height="size"
ID="string"
Nullable="True|False"
ParameterName="string"
Style="string"
TabIndex="integer"
TargetControlId="string"
TargetDataSourceId="string"
ToolTip="string"
Visible="True|False"
Width="size" >
<ListItem Value="1">Item1</ListItem>
<ListItem Value="2">Item2</ListItem>
...
</DropDownList>
<FileUpload>
<FileUpload
ID="string"
DataField="string"
DataType="string"
DisplayMode="FilePicker|FilePickerNoUpload|UploadAndSelect"
Extensions="comma-delimited list of extensions"
FileNameLabelCssClass="string|Normal"
MessageLabelCssClass="string|Normal"
NewFileButtonCssClass="string|CommandButton"
NewFileButtonText="string|Upload File"
Nullable="True|False"
Path="string"
UploadButtonCssClass="string|CommandButton"
UploadButtonText="string|Upload"
UseUniqueFileName="True|False"
Visible="True|False"
/>
<HtmlInput>
<HtmlInput
DataField="string"
DataType="string"
Height="size"
ID="string"
Nullable="True|False"
Visible="True|False"
Width="size"
/>
<Label>
<Label
ID="string"
For="string"
Text="string"
CssClass="string"
Visible="True|False"
/>
<ListBox>
<ListBox
AppendDataBoundItems="True|False"
CssClass="string"
DataField="string"
DataSourceID="string"
DataTextField="string"
DataType="string|int32|...."
DataValueField="string"
Height="size"
ID="string"
Rows="integer"
SelectedItemsSeparator="string||"
SelectionMode="Single|Multiple"
Style="string"
TabIndex="integer"
ToolTip="string"
Visible="True|False"
Width="size">
<ListItem Value="1">Item1</ListItem>
<ListItem Value="2">Item2</ListItem>
...
</ListBox>
<Panel>
<Panel
CssClass="string"
Height="size"
ID="string"
ShowIf="Expression"
ShowRoles="Role1Name,Role2Name"
Style="string"
Visible="True|False"
Width="size"
Wrap="True|False">
...HTML, Text, and Control Tags...
</Panel>
<Password>
<Password
CssClass="string"
DataField="string"
DataType="string|int32|int64|boolean|...."
Height="size"
ID="string"
MaxLength="integer"
Nullable="True|False"
ReadOnly="True|False"
Style="string"
TabIndex="integer"
ToolTip="string"
Visible="True|False"
Width="size"
/>
<RadioButtonList>
<RadioButtonList
AppendDataBoundItems="True|False"
CssClass="string"
DataSourceID="string"
DataTextField="string"
DataTextFormatString="string"
DataValueField="string"
Height="size"
ID="string"
Nullable="True|False"
RepeatColumns="integer"
RepeatDirection="Horizontal|Vertical"
RepeatLayout="Table|Flow"
Style="string"
TabIndex="integer"
ToolTip="string"
Visible="True|False"
Width="size">
<ListItem value="1">Item1</ListItem >
<ListItem value="2">Item2</ListItem >
...
</RadioButtonList>
<Textbox>
<Textbox
CssClass="string"
DataField="string"
DataType="string|int32|int64|boolean|...."
HtmlEncode="True|False"
ID="string"
MaxLength="integer"
Nullable="True|False"
Placeholder="string"
ReadOnly="True|False"
Style="string"
TabIndex="integer"
ToolTip="string"
Visible="True|False"
Width="size"
/>
<Textarea>
<Textarea
Columns="integer"
CssClass="string"
DataField="string"
DataType="string|int32|int64|boolean|...."
Height="size"
HtmlEncode="True|False"
ID="string"
MaxLength="integer"
Nullable="True|False"
ReadOnly="True|False"
Rows="integer"
Style="string"
TabIndex="integer"
ToolTip="string"
Visible="True|False"
Width="size"
Wrap="True|False"
/>
<UpdateButton>
<UpdateButton
CssClass="string"
Height="size"
OnClientClick="string"
Style="string"
TabIndex="integer"
Text="string"
ToolTip="string"
Visible="True|False"
Width="size"
<Command ... />
/>
Take a look at the XMod Pro official documentation on the <CommandButton>
control. In Form.X, the
<UpdateButton>
supports the nested commands. This allows you to target your other templates by ID. For example,
if you update a record in a table, Form.X does not take the liberty of refreshing your template. You do this by
targetting the template via command tags. See the recipes section for examples.
<Validate> (Checkbox)
<Validate
CssClass="string"
Display="Static|Dynamic"
Message="string"
Target="string"
Text="string"
Type="Checkbox"
Width="size"
/>
<Validate> (CheckboxList)
<Validate
CssClass="string"
Display="Static|Dynamic"
Message="string"
Target="string"
Text="string"
Type="CheckboxList"
Width="size"
/>
<Validate> (Compare)
<Validate
CompareTarget="string"
CompareValue="string"
CssClass="string"
DataType="String|Integer|Double|Date|Currency"
Display="Static|Dynamic"
EnableClientScript="True|False"
Height="size"
Message="string"
Operator="Equal|NotEqual|GreaterThan|GreaterThanEqual|LessThan|LessThanEqual|DataTypeCheck"
Target="string"
Text="string"
Type="Compare"
Width="size"
/>
<Validate> (Email)
<Validate
CssClass="string"
Display="Static|Dynamic"
Message="string"
Target="string"
Text="string"
Type="Email"
Width="size"
/>
<Validate> (Range)
<Validate
CssClass="string"
DataType="String|Integer|Double|Date|Currency"
Display="Static|Dynamic"
EnableClientScript="True|False"
Height="size"
MaximumValue="string"
Message="string"
MinimumValue="string"
Target="string"
Text="string"
Type="Range"
Width="size"
/>
<Validate> (Regular Expression)
<Validate
CssClass="string"
Display="Static|Dynamic"
EnableClientScript="True|False"
Height="size"
Message="string"
Target="string"
Text="string"
Type="RegEx"
ValidationExpression="string"
Width="size"
/>
<Validate> (Required)
<Validate
CssClass="string"
Display="Static|Dynamic"
EnableClientScript="True|False"
Height="size"
Message="string"
Target="string"
Text="string"
Type="Required"
Width="size"
/>
<Validate> (Action)
<Validate Type="Action" />
This validator should be used in addition to the <ValidationSummary>
control when you want to report form action
errors back to the user. For example, when using the <AddUser>
action, if the username they choose is invalid,
you'll want to let them know about it in a friendly way.
<ValidationSummary>
<ValidationSummary
CssClass="string"
DisplayMode="List|BulletList|SingleParagraph"
EnableClientScript="True|False"
HeaderText="string"
Height="size"
Width="size"
/>
Form Actions
Using a token from your
<SelectCommand>
<Email PerformAction="{{TokenFromSelect}}" ... >Email Body</Email>
Using a token from your form controls
<Email PerformAction="{{AgreeToTerms}}" ... >Email Body</Email>
Using an expression from your form controls
<Email PerformAction="{{Department}} = Sales" ... >Email Body</Email>
Using an output parameter from your
<SubmitCommand>
<SubmitCommand CommandText="StoredProcedureName" CommandType="StoredProcedure">
<Parameter Name="UserID" />
<Parameter Name="SendEmail" DataType="Boolean" Direction="Output" />
</SubmitCommand>
<Email PerformAction="{{SendEmail}}" ... >Email Body</Email>
Form actions can execute before or after the submit command in a form. This is controlled by a property available on all
form actions called Event
(PreSubmit or PostSubmit) which defaults to PostSubmit
. This is helpful when you need a value
emitted from a form action for your actual <SubmitCommand>
. A good example would be the <AddUser>
action, in the
event that you want to execute a stored procedure after the creation of the user, without having to rely on database triggers. An example
of this is provided in the <AddUser>
action.
In addition, all form actions have a shared property called PerformAction
which if used,
must evaluate to True
or False
. This value is True
by default if not otherwise specified. Only simple expressions are allowed.
This is slightly different compared to core XMod Pro forms. For example, SendIf
is used in the XMod Pro <Email>
action. With
Form.X, all actions are controlled by the PerformAction
property.
See the code examples on the right.
Properties available on all form actions
Name | Type | Default | Explanation |
---|---|---|---|
PerformAction | Boolean Expression | True | Either a value that can be cast to True or False (i.e. True, 1, False, 0) or a simple expression as shown in the code examples. |
Event | String | PostSubmit | PreSubmit will execute the action prior to the <SubmitCommand> , whereas PostSubmit will execute afterwards. |
<Email>
> Basic Example
<Email
To="{{EmailAddress}}"
From="change@me.com"
Subject="{{Firstname}}, thank you for contacting us!">
Thanks {{Firstname}}. We received your request. We'll get back to you ASAP!
</Email>
> All Options
<Email
To="sales@me.com"
From="change@me.com"
CC="john@doe.com,jane@doe.com"
BCC="site@admin.com"
ReplyTo="{{Email}}"
Format="Text"
Event="PostSubmit"
PerformAction="{{Department}} = Sales"
Subject="You received a request from {{Firstname}}">
Name: {{Firstname}} {{Lastname}}
Email: {{Email}}
Message: {{Message}}
</Email>
The <Email>
action will send an email.
Name | Type | Required | Default | Explanation |
---|---|---|---|---|
To | String | True | Nothing | A comma-delimited list of email addresses. |
From | String | True | Nothing | An email address that the email is coming from |
CC | String | False | Nothing | A comma-delimieted list of email addresses. |
BCC | String | False | Nothing | A comma-delimieted list of email addresses. |
ReplyTo | String | False | Nothing | If used, this will be the reply-to address set on the email. |
Subject | String | True | Nothing | The subject of the email |
Format | String | False | Text | Text or Html - The format of the email |
PerformAction | Boolean Expression | False | True | See main Form Actions topic |
Event | String | False | PostSubmit | See main Form Actions topic |
<AddUser>
Simple example
<AddUser
Approved="True|False"
City="string"
Country="string"
DisplayName="string"
Email="string"
ErrMsgDuplicateEmail="string"
ErrMsgDuplicateUser="string"
ErrMsgDuplicateUsername="string"
ErrMsgInvalidEmail="string"
ErrMsgInvalidPassword="string"
ErrMsgInvalidUsername="string"
FirstName="string"
LastName="string"
Password="string"
PostalCode="string"
Region="string"
RoleNames="comma-delimited list of DNN roles"
Street="string"
SendVerificationEmail="True|False"
Telephone="string"
Unit="string"
UpdatePasswordOnNextLogin="True|False"
Username="string">
PerformAction="Boolean Expression"
Event="PostSubmit|PreSubmit">
(NOTE: Property tags are optional)
<Property Name="string" Value="string" />
...Additional Property Tags as needed...
</AddUser>
If you set Event="PreSubmit", you can do this:
<SubmitCommand CommandText="INSERT INTO SomeOtherTable ( UserID ) VALUES ( @UserID )">
<Parameter Name="UserID" Value="{{__UserId}}" DataType="Int32" />
</SubmitCommand>
Creates a DNN user account on the site. The token {{__UserId}} is passed down stream and available to other actions, including your <SubmitCommand>
if you set the Event to "PreSubmit".
A great example of leveraging this feature is if you wanted to execute your <SubmitCommand>
after the creation of the user.
See the code example on the right as an example.
Name | Type | Required | Default | Explanation |
---|---|---|---|---|
Approved | Boolean | False | False | Whether or not the user account is approved |
Username | String | True | Nothing | The username of the user |
String | True | Nothing | The email address of the user | |
FirstName | String | False | Nothing | The first name of the user |
LastName | String | False | Nothing | The last name of the user |
DisplayName | String | False | Nothing | The display name of the user |
Password | String | True | Nothing | The password of the user |
RoleNames | String | False | Nothing | A comma-delimited list of DNN role names to assign to the user |
Street | String | False | Nothing | The street address of the user |
Unit | String | False | Nothing | The unit address of the user |
City | String | False | Nothing | The city of the user |
PostalCode | String | False | Nothing | The postal code of the user |
Region | String | False | Nothing | The region/state of the user |
Country | String | False | Nothing | The country of the user |
Telephone | String | False | Nothing | The telephone of the user |
SendVerificationEmail | Boolean | False | False | Whether or not to send the default DNN verification email |
UpdatePasswordOnNextLogin | Boolean | False | False | Force the user to change their password on the next login |
ErrMsgDuplicateEmail | String | False | The email address already exists | Optional error message override |
ErrMsgDuplicateUser | String | False | The user is already registered | Optional error message override |
ErrMsgDuplicateUsername | String | False | The username already exists | Optional error message override |
ErrMsgInvalidEmail | String | False | The supplied email is invalid | Optional error message override |
ErrMsgInvalidPassword | String | False | The supplied password is invalid | Optional error message override |
ErrMsgInvalidUsername | String | False | The supplied username is invalid | Optional error message override |
<Property> | Profile Property | False | Nothing | Nested profile property tags - See below this table |
PerformAction | Boolean Expression | False | True | See main Form Actions topic |
Event | String | False | PostSubmit | See main Form Actions topic |
Nested Profile Property Tags
You can optionally nest <Property>
tags within this action to target other profile properties. This is also helpful
due to the variations in how DNN handles user accounts between versions. If you find one of the main properties is not
setting the value upon creation, try adding it as a nested <Property>
tag.
Name | Type | Required | Default | Explanation |
---|---|---|---|---|
Name | String | True | Nothing | The profile property name |
Value | String | True | Nothing | The value to set |
<AddToRoles>
<AddToRoles
EndDate="date"
RoleNames="comma-delimited list of DNN roles"
StartDate="date"
UserId="integer"
PerformAction="Boolean Expression"
Event="PostSubmit|PreSubmit"
/>
<SqlCommand>
<SqlCommand
CommandText="string"
CommandType="Text|StoredProcedure"
ConnectionString="string"
PerformAction="Boolean Expression"
Event="PostSubmit|PreSubmit">
... optional list of parameters
<Parameter Name="string" Value="..." DefaultValue="..." DataType="..." Direction="Input|Output" />
</SqlCommand>
The <SqlCommand>
action works just like the <SubmitCommand>
but can be executed afterwards unless otherwise specified in the
event. For example, you may want to trigger a SQL command after another form action executes.
Name | Type | Required | Default | Explanation |
---|---|---|---|---|
CommandText | String | True | Nothing | Either a SQL command or the name of a stored procedure |
CommandType | String | False | Text | Text or StoredProcedure |
ConnectionString | String or [[ConnectionString:Name]] | False | Site's Connection String | The connection string to use for the command |
PerformAction | Boolean Expression | False | True | See main Form Actions topic |
Event | String | False | PostSubmit | See main Form Actions topic |
<Twilio>
<Twilio
AccountSid="string"
AuthToken="string"
From="string"
To="string"
PerformAction="Boolean Expression"
Event="PostSubmit|PreSubmit">
Text message goes here...
</Twilio>
The <Twilio>
action sends one or more text messages (Separate with pipe ("|") character). An account with Twilio is required.
Name | Type | Required | Default | Explanation |
---|---|---|---|---|
AccountSID | String | True | Nothing | Your AccountSid from Twilio |
AuthToken | String | True | Nothing | Your Auth Token (Secret key) from Twilio |
From | String | True | Nothing | The number from your Twilio account to send the text from |
PerformAction | Boolean Expression | False | True | See main Form Actions topic |
Event | String | False | PostSubmit | See main Form Actions topic |
<UpdateUser>
<UpdateUser
Approved="True|False"
City="string"
Country="string"
DisplayName="string"
Email="string"
ErrMsgUserNotFound="string"
ErrMsgInvalidPassword="string"
ErrMsgOther="string"
FirstName="string"
LastName="string"
NewPassword="string"
OldPassword="string"
PostalCode="string"
Region="string"
Street="string"
Telephone="string"
Unit="string"
UpdatePasswordOnNextLogin="True|False"
UserId="integer"
PerformAction="Boolean Expression"
Event="PostSubmit|PreSubmit">
(NOTE: Property tags are optional)
<Property Name="string" Value="string" />
...Additional Property Tags as needed...
</UpdateUser>
Updates a DNN user account.
New to version 1.3, you no longer have to specify the user's old password when changing their password. This is useful for administrators, but use with caution!
<SendPassword>
<SendPassword
Username="string"
Email="string"
CannotSend="string"
PerformAction="Boolean Expression"
Event="PostSubmit|PreSubmit">
</SendPassword>
Initiates a password reset by sending an email to the requester. The core send password control within DNN takes care of the small details like determining whether or not to show the email field (e.g. Site requires a unique email address) or the username field. In the case of Form.X, you should check these internal settings yourself and be sure the form that you create is appropriate based on your site settings. This action currently does not support a security question and answer.
<SilentPost>
<SilentPost
Url="string"
PerformAction="Boolean Expression"
Event="PostSubmit|PreSubmit">
One or more optional field tags
<Field name="string" value="string" />
</SilentPost>
Executes a post request behind the scenes to a designated endpoint (Url). You can optionally nest <Field>
tags within this
action to send to the endpoint.
Reactivity
Using a
<Dropdownlist>
<Dropdownlist Id="Department" Datafield="Department" Reactive="True">
<ListItem Value="Sales">Sales</ListItem>
<ListItem Value="Support">Support</ListItem>
</Dropdownlist>
<Panel ShowIf="{{Department}} = Support">
<Textbox Id="CustomerNumber" Datafield="CustomerNumber" />
<Validate Type="Required" Target="CustomerNumber" Text="Required" Message="You must enter your customer number" />
</Panel>
Imagine you have a form where you want to show/hide or make certain fields required based on other selections. Previously we handled this with some JavaScript magic and/or database validation.
Reactivity is an experimental feature that introduces dynamic fields and validation, so you can skip all the fancy JavaScript and database validation,
and simply define rules to <Panel>
tags. This is a complex integration so the implementation may change, so be sure to check
release notes for future versions.
Current supported controls that can trigger the ShowIf
property of a <Panel>
:
<Dropdownlist>
<Checkbox>
All you have to do is set Reactive="True"
to the above listed controls, and all the <Panel>
controls within the form will re-evaluate their
ShowIf
property.
See the code examples on the right.
Recipes
Contact Form
<xmod:Register TagPrefix="fx"
Namespace="Reflect.XModPro.Templates.FormX"
Assembly="Reflect.XModPro.Templates.FormX" />
<xmod:Template Id="ContactUs" Ajax="True">
<DetailDataSource CommandText="SELECT 1" />
<DetailTemplate>
<fx:FormX Mode="Add">
<addform>
<div class="form-group">
<label for="Firstname">First name</label>
<Textbox Id="Firstname" Datafield="Firstname" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Lastname">Last name</label>
<Textbox Id="Lastname" Datafield="Lastname" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Comments">Comments</label>
<Textbox Id="Comments" Datafield="Comments" CssClass="form-control" />
</div>
<AddButton Text="Send Message" CssClass="btn btn-primary" />
<Email To="email@change.me" From="email@change.me" Subject="Message from {{Firstname}}" Format="Text">
Hello. You got a message:
Name: {{Firstname}}
Last Name: {{Lastname}}
Comments: {{Comments}}
</Email>
</addform>
<addsuccesstemplate>
<div class="alert alert-success">
<p>
Thanks, {{Firstname}}! We'll get back to you ASAP!
</p>
</div>
<ContinueButton Text="Continue" CssClass="btn btn-default" />
</addsuccesstemplate>
</fx:FormX>
</DetailTemplate>
</xmod:Template>
Registration Form
<xmod:Register TagPrefix="fx"
Namespace="Reflect.XModPro.Templates.FormX"
Assembly="Reflect.XModPro.Templates.FormX" />
<xmod:Template Ajax="True">
<DetailDataSource CommandText="SELECT 1"/>
<DetailTemplate>
<fx:FormX Mode="Add">
<addform>
<div class="form">
<div class="form-group">
<label for="Firstname">First name</label>
<Textbox Id="Firstname" Datafield="Firstname" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Lastname">Last name</label>
<Textbox Id="Lastname" Datafield="Lastname" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Email">Email</label>
<Textbox Id="Email" Datafield="Email" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Username">Username</label>
<Textbox Id="Username" Datafield="Username" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Password">Password</label>
<Password Id="Password" Datafield="Password" Datatype="String" CssClass="form-control" />
</div>
<ValidationSummary />
<Validate Type="Action" />
<AddButton Text="Register" CssClass="btn btn-primary" />
<AddUser
Approved="True"
Email="{{Email}}"
FirstName="{{FirstName}}"
LastName="{{LastName}}"
Password="{{Password}}"
RoleNames="Registered Users"
Username="{{Username}}">
</AddUser>
</div>
</addform>
<addsuccesstemplate>
<div class="alert alert-success">
Success
</div>
<ContinueButton Text="Continue" CssClass="btn btn-default" />
</addsuccesstemplate>
</fx:FormX>
</DetailTemplate>
</xmod:Template>
User Management
<xmod:Register TagPrefix="fx"
Namespace="Reflect.XModPro.Templates.FormX"
Assembly="Reflect.XModPro.Templates.FormX" />
<xmod:Template UsePaging="True" Ajax="True">
<ListDataSource CommandText="SELECT [UserId], [PortalId], [Username], [FirstName], [LastName] FROM vw_Users"/>
<DetailDataSource CommandText="SELECT [UserId], [PortalId], [Username], [FirstName], [LastName], [DisplayName], [IsSuperUser], [Email], [VanityUrl], [AffiliateId], [IsDeleted], [RefreshRoles], [LastIPAddress], [UpdatePassword], [PasswordResetToken], [PasswordResetExpiration], [Authorised], [CreatedByUserId], [CreatedOnDate], [LastModifiedByUserId], [LastModifiedOnDate] FROM vw_Users WHERE [UserId] = @UserId">
<Parameter Name="UserId" />
</DetailDataSource>
<HeaderTemplate>
<table class="table table-striped">
<thead>
<tr>
<th>User Id</th>
<th>Portal Id</th>
<th>Username</th>
<th>First Name</th>
<th>Last Name</th>
<th> </th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>[[UserId]]</td>
<td>[[PortalId]]</td>
<td>[[Username]]</td>
<td>[[FirstName]]</td>
<td>[[LastName]]</td>
<td>
<xmod:DetailLink Text="Details">
<Parameter Name="UserId" Value='[[UserId]]' />
</xmod:DetailLink>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
<DetailTemplate>
<fx:FormX>
<template>
<strong>UserId</strong> [[UserId]]<br />
<strong>Username</strong> [[Username]]<br />
<strong>FirstName</strong> [[FirstName]]<br />
<strong>LastName</strong> [[LastName]]<br />
<strong>DisplayName</strong> [[DisplayName]]<br />
<strong>Email</strong> [[Email]]<br />
<fx:EditButton CssClass="btn btn-primary" Text="Edit">
<Parameter Name="UserId" Value='[[UserId]]' DataType="Int32" />
</fx:EditButton>
<xmod:ReturnLink CssClass="dnnSecondaryAction" Text="<< Return" />
</template>
<editform>
<SelectCommand CommandText="SELECT * FROM vw_Users WHERE UserID = @UserId" />
<div class="form">
<div class="form-group">
<label for="Firstname">First name</label>
<Textbox Id="Firstname" Datafield="Firstname" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Lastname">Last name</label>
<Textbox Id="Lastname" Datafield="Lastname" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Email">Email</label>
<Textbox Id="Email" Datafield="Email" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="Telephone">Telephone</label>
<Textbox Id="Telephone" Datafield="Telephone" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="NewPassword">New Password</label>
<Password Id="NewPassword" Datafield="NewPassword" Datatype="String" CssClass="form-control" />
</div>
<div class="form-group">
<label for="OldPassword">Old Password</label>
<Password Id="OldPassword" Datafield="OldPassword" Datatype="String" CssClass="form-control" />
</div>
<Textbox Id="UserId" Datafield="UserId" DataType="Int32" Visible="False" />
<ValidationSummary />
<Validate Type="Action" />
<UpdateButton Text="Update User" CssClass="btn btn-primary" />
<UpdateUser
UserId="{{UserId}}"
Approved="True"
Email="{{Email}}"
FirstName="{{FirstName}}"
LastName="{{LastName}}"
NewPassword="{{NewPassword}}"
OldPassword="{{OldPassword}}"
Telephone="{{Telephone}}">
<Property Name="Telephone" Value="{{Telephone}}" />
</UpdateUser>
</div>
<CancelButton CssClass="btn btn-default" Text="Cancel" />
</editform>
<editsuccesstemplate>
<div class="alert alert-success">
Success!
</div>
<ContinueButton Text="Continue">
<Command Type="Detail">
<Parameter Name="UserId" Value="{{UserId}}" DataType="Int32" />
</Command>
</ContinueButton>
</editsuccesstemplate>
</fx:FormX>
</DetailTemplate>
</xmod:Template>
Inline Editing
<xmod:Register TagPrefix="fx" Namespace="Reflect.XModPro.Templates.FormX" Assembly="Reflect.XModPro.Templates.FormX" />
<xmod:Template id="Contacts" Ajax="True">
<ListDataSource CommandText="SELECT *, (SELECT Text FROM dbo.Lists WHERE EntryId = c.Country) AS CountryText FROM dbo.XMP_Contact c ORDER BY ID" />
<DeleteCommand CommandText="DELETE FROM dbo.XMP_Contact WHERE ID = @ID">
<Parameter Name="ID" />
</DeleteCommand>
<SearchSort FilterExpression="Firstname LIKE '%{0}%'" />
<HeaderTemplate>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Country</th>
<th>State</th>
<th>Favorite</th>
<th></th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<fx:FormX Mode="Template" EditRoles="Registered Users" AddRoles="Registered Users">
<Template>
<td>[[ID]]</td>
<td>[[Firstname]]</td>
<td>[[Lastname]]</td>
<td>[[CountryText]]</td>
<td>[[State]]</td>
<td>[[Favorite]]</td>
<td style="width: 1%; white-space: nowrap">
<fx:EditButton Text="Edit" CssClass="btn btn-default btn-xs">
<Parameter Name="ID" Value='[[ID]]' DataType="Int32" />
</fx:EditButton>
<xmod:DeleteButton Text="Delete" CssClass="btn btn-danger btn-xs">
<Parameter Name="ID" Value='[[ID]]' DataType="Int32" />
</xmod:DeleteButton>
</td>
</Template>
<EditForm>
<SelectCommand CommandText="dbo.XMP_GetContact" CommandType="StoredProcedure">
<Parameter Name="ID" />
</SelectCommand>
<SubmitCommand CommandText="UPDATE dbo.XMP_Contact SET Firstname=@Firstname, Lastname=@Lastname, State=@State, Country=@Country, Favorite=@Favorite WHERE ID = @ID" />
<ControlDataSource Id="cds_Countries" CommandText="SELECT Text, EntryID FROM Lists WHERE ListName='Country' ORDER BY Text" />
<ControlDataSource id="cds_Regions" CommandText="SELECT Text, Value FROM Lists WHERE ParentID=@ParentID" >
<Parameter Name="ParentID" />
</ControlDataSource>
<td>[[ID]]</td>
<td><Textbox Id="Firstname" Datafield="Firstname" Datatype="String" CssClass="form-control" /><Validate Type="Required" Target="Firstname" Text="* Required" Message="First name is required" EnableClientScript="False" /></td>
<td><Textbox Id="Lastname" Datafield="Lastname" Datatype="String" CssClass="form-control" /></td>
<td>
<DropdownList Id="Country" DataField="Country" DataType="string" DataTextField="Text" DataValueField="EntryID" DataSourceId="cds_Countries" TargetDataSourceId="cds_Regions" ParameterName="ParentID" TargetControlId="State" AppendDataBoundItems="True" CssClass="form-control">
<ListItem Value="">Select</ListItem>
</DropdownList>
</td>
<td>
<DropdownList Id="State" DataField="State" DataType="string" DataTextField="Text" DataValueField="Value" DataSourceId="cds_Regions" AppendDataBoundItems="True" CssClass="form-control">
<ListItem Value="">Select</ListItem>
</DropdownList>
</td>
<td>
<Checkbox Id="Favorite" Datafield="Favorite" Datatype="Boolean" Nullable="False" />
</td>
<td style="width: 1%; white-space: nowrap">
<UpdateButton Text="Save" CssClass="btn btn-default btn-xs">
<Command Type="List" />
</UpdateButton>
<CancelButton Text="Cancel" CssClass="btn btn-default btn-xs" />
</td>
<Textbox Id="ID" Datafield="ID" DataType="Int32" Visible="False" />
</EditForm>
</fx:FormX>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody></table>
</FooterTemplate>
</xmod:template>
This example demonstrates how you can embed Form.X within an <ItemTemplate>
, allowing you to edit items without a page refresh.
Inline Editing (Retain Pagination)
<xmod:Register TagPrefix="fx"
Namespace="Reflect.XModPro.Templates.FormX"
Assembly="Reflect.XModPro.Templates.FormX" />
<xmod:Template id="Contacts" Ajax="True">
<ListDataSource CommandText="SELECT *, (SELECT Text FROM dbo.Lists WHERE EntryId = c.Country) AS CountryText FROM dbo.XMP_Contact c ORDER BY ID" />
<DeleteCommand CommandText="DELETE FROM dbo.XMP_Contact WHERE ID = @ID">
<Parameter Name="ID" />
</DeleteCommand>
<SearchSort FilterExpression="Firstname LIKE '%{0}%'" />
<CustomCommands>
<DataCommand CommandName="UpdateContact" CommandText="UPDATE dbo.XMP_Contact SET Firstname=@Firstname, Lastname=@Lastname, State=@State, Country=@Country, Favorite=@Favorite WHERE ID = @ID" />
</CustomCommands>
<HeaderTemplate>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Country</th>
<th>State</th>
<th>Favorite</th>
<th></th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<fx:FormX Mode="Template">
<Template>
<td>[[ID]]</td>
<td>[[Firstname]]</td>
<td>[[Lastname]]</td>
<td>[[CountryText]]</td>
<td>[[State]]</td>
<td>[[Favorite]]</td>
<td style="width: 1%; white-space: nowrap">
<fx:EditButton Text="Edit" CssClass="btn btn-default btn-xs">
<Parameter Name="ID" Value='[[ID]]' DataType="Int32" />
</fx:EditButton>
<xmod:DeleteButton Text="Delete" CssClass="btn btn-danger btn-xs">
<Parameter Name="ID" Value='[[ID]]' DataType="Int32" />
</xmod:DeleteButton>
</td>
</Template>
<EditForm>
<SelectCommand CommandText="dbo.XMP_GetContact" CommandType="StoredProcedure">
<Parameter Name="ID" />
</SelectCommand>
<ControlDataSource Id="cds_Countries" CommandText="SELECT Text, EntryID FROM Lists WHERE ListName='Country' ORDER BY Text" />
<ControlDataSource id="cds_Regions" CommandText="SELECT Text, Value FROM Lists WHERE ParentID=@ParentID" >
<Parameter Name="ParentID" />
</ControlDataSource>
<td>[[ID]]</td>
<td><Textbox Id="Firstname" Datafield="Firstname" Datatype="String" CssClass="form-control" /><Validate Type="Required" Target="Firstname" Text="* Required" Message="First name is required" EnableClientScript="False" /></td>
<td><Textbox Id="Lastname" Datafield="Lastname" Datatype="String" CssClass="form-control" /></td>
<td>
<DropdownList Id="Country" DataField="Country" DataType="string" DataTextField="Text" DataValueField="EntryID" DataSourceId="cds_Countries" TargetDataSourceId="cds_Regions" ParameterName="ParentID" TargetControlId="State" AppendDataBoundItems="True" CssClass="form-control">
<ListItem Value="">Select</ListItem>
</DropdownList>
</td>
<td>
<DropdownList Id="State" DataField="State" DataType="string" DataTextField="Text" DataValueField="Value" DataSourceId="cds_Regions" AppendDataBoundItems="True" CssClass="form-control">
<ListItem Value="">Select</ListItem>
</DropdownList>
</td>
<td>
<Checkbox Id="Favorite" Datafield="Favorite" Datatype="Boolean" Nullable="False" />
</td>
<td style="width: 1%; white-space: nowrap">
<ValidationSummary />
<Validate Type="Select" />
<UpdateButton Text="Save" CssClass="btn btn-default btn-xs">
<Command Type="Custom" Name="UpdateContact">
<Parameter Name="ID" Value="{{ID}}" DataType="Int32" />
<Parameter Name="Firstname" Value="{{Firstname}}" />
<Parameter Name="Lastname" Value="{{Lastname}}" />
<Parameter Name="Country" Value="{{Country}}" />
<Parameter Name="State" Value="{{State}}" />
<Parameter Name="Favorite" Value="{{Favorite}}" />
</Command>
</UpdateButton>
<CancelButton Text="Cancel" CssClass="btn btn-default btn-xs" />
</td>
<Textbox Id="ID" Datafield="ID" DataType="Int32" Visible="False" />
</EditForm>
</fx:FormX>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</xmod:template>
This example demonstrates how you can embed Form.X within an <ItemTemplate>
, allowing you to edit items without a page refresh.
The difference between this example and the inline editing example is the pagination. When you target a template (i.e. <Command Type="List" Target="TemplateId" />
)
it causes the template to rebind its data. However, if you have a large set of data and want to retain pagination, you
can use a custom command structure instead of a <SubmitCommand>
.
Search / Sort
<xmod:Register TagPrefix="fx"
Namespace="Reflect.XModPro.Templates.FormX"
Assembly="Reflect.XModPro.Templates.FormX" />
<xmod:Template Id="SearchSort" Ajax="True">
<DetailDataSource CommandText="SELECT @Query AS Query">
<Parameter Name="Query" />
</DetailDataSource>
<DetailTemplate>
<fx:FormX Mode="Add">
<AddForm>
<Textbox Id="Query" Datafield="Query" CssClass="" />
<AddButton Text="Go" CssClass="btn btn-default">
<Command Type="Detail">
<Parameter Name="Query" Value="{{Query}}" />
</Command>
<Command Type="List" Target="Results">
<Parameter Name="Query" Value="{{Query}}" />
</Command>
</AddButton>
</AddForm>
</fx:FormX>
</DetailTemplate>
</xmod:Template>
<xmod:Template id="Results" Ajax="True">
<ListDataSource CommandText="SELECT * FROM dbo.YourTable WHERE SomeField LIKE '%' + @Query + '%'">
<Parameter Name="Query" />
</ListDataSource>
<ItemTemplate>...</ItemTemplate>
</xmod:Template>
You can completely replace the default <SearchSort>
control and use FormX within another template to filter results.
The example on the right has two <xmod:Template>
tags, both with IDs assigned. The top template contains a <Texbox>
for a query.
Notice that the <AddButton>
has two nested commands. One (i.e. Type="Detail") targets itself so that it retains the previous search value
when the form is submitted. The second one (i.e. Type="List") targets the bottom template.
How powerful is this? I'm glad you asked... You can essentially dream up of any type of advanced filter with all kinds of controls and voila! You have your own custom search/sort replacement.
This is similar to putting a separate form on the page, but in the case of FormX, it's blazing fast, and with Ajax set to true, no page refresh either!
Release Notes
Version 1.3.0
Released 12/19/2018
New Features
Reactive
experimental property added to several controls that when used in conjunction with the<Panel>
tag can dynamically show and hide fields, including their validation. See Reactivity for details. This feature may undergo implementation changes so be sure to check the release notes for any potential breaking changes in future updates.PerformAction
property added to all form actions, which can evaluate a simple expression to determine whether or not the action will execute.Event
property added to all form actions. You can now set the action to execute before or after (default) the<SubmitCommand>
. A great example of this is found in the<AddUser>
action documentation.<SilentPost>
form action added<SqlCommand>
form action added<Twilio>
form action added (Send SMS messages)<UpdateUser>
form action now allows you to change a user's password without requiring their old password. This is useful for administrators.- New recipes!
Bug Fixes
<SendPassword>
form action not setting token expiration in some cases.
Version 1.2.3
New Features
<SendPassword>
form action added- ClientName support added to forms
Bug Fixes
- Token replacement minor fixes
- Database validation not returning @ERROR in some cases (Credit to Catalin)
Version 1.2.2
New Features
- Added support for output parameters in forms
<Validate Type="Database" />
added to support @ERROR database validation only. See XMP docs- New recipes!
Version 1.2.1
New Features
<UpdateUser>
form action added<Captcha>
validator added for forms<Validate Type="Action" />
added to support form action validation- Added support for FormX within DetailTemplate loaded via
<xmod:DetailButton>
- New recipes!
Bug Fixes
- Token replacement minor fixes
Version 1.1.0
New Features
<AddUser>
form action added<AddToRoles>
form action added
Bug Fixes
- Success template shown after error in form action
Version 1.0.0
Released on 10/22/2018
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.