Tag helper document for dynamic forms and form elements

resolves https://github.com/abpframework/abp/issues/3199
pull/3607/head
Yunus Emre Kalkan 6 years ago
parent d83a24a2f7
commit 9c2eac583a

@ -1,3 +1,277 @@
## Dynamic Forms
# Dynamic Forms
`Warning:` Before getting into this document, be sure that you have clearly understood [abp form elements](Form-elements.md) document.
## Introduction
`abp-dynamic-form` creates a bootstrap form for a given c# model.
Basic usage:
````xml
<abp-dynamic-form abp-model="@Model.MyDetailedModel"/>
````
Model:
````csharp
public class DynamicFormsModel : PageModel
{
[BindProperty]
public DetailedModel MyDetailedModel { get; set; }
public List<SelectListItem> CountryList { get; set; } = new List<SelectListItem>
{
new SelectListItem { Value = "CA", Text = "Canada"},
new SelectListItem { Value = "US", Text = "USA"},
new SelectListItem { Value = "UK", Text = "United Kingdom"},
new SelectListItem { Value = "RU", Text = "Russia"}
};
public void OnGet()
{
MyDetailedModel = new DetailedModel
{
Name = "",
Description = "Lorem ipsum dolor sit amet.",
IsActive = true,
Age = 65,
Day = DateTime.Now,
MyCarType = CarType.Coupe,
YourCarType = CarType.Sedan,
Country = "RU",
NeighborCountries = new List<string>() { "UK", "CA" }
};
}
public class DetailedModel
{
[Required]
[Placeholder("Enter your name...")]
[Display(Name = "Name")]
public string Name { get; set; }
[TextArea(Rows = 4)]
[Display(Name = "Description")]
[InputInfoText("Describe Yourself")]
public string Description { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Is Active")]
public bool IsActive { get; set; }
[Required]
[Display(Name = "Age")]
public int Age { get; set; }
[Required]
[Display(Name = "My Car Type")]
public CarType MyCarType { get; set; }
[Required]
[AbpRadioButton(Inline = true)]
[Display(Name = "Your Car Type")]
public CarType YourCarType { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Day")]
public DateTime Day { get; set; }
[SelectItems(nameof(CountryList))]
[Display(Name = "Country")]
public string Country { get; set; }
[SelectItems(nameof(CountryList))]
[Display(Name = "Neighbor Countries")]
public List<string> NeighborCountries { get; set; }
}
public enum CarType
{
Sedan,
Hatchback,
StationWagon,
Coupe
}
}
````
## Demo
See the [dynamic forms demo page](https://bootstrap-taghelpers.abp.io/Components/DynamicForms) to see it in action.
## Attributes
### abp-model
Sets the c# model for dynamic form. Properties of this modal are turned into inputs in the form.
### submit-button
Can be `True` or `False`.
If `True`, a submit button will be generated at the bottom of the form.
Default value is `False`.
### required-symbols
Can be `True` or `False`.
If `True`, required inputs will have a symbol (*) that indicates they are required.
Default value is `True`.
## Form Content Placement
By default, `abp-dynamicform` clears the inner html and places the inputs into itself. If you want to add additional content to dynamic form or place the inputs to some specific area, you can use ` <abp-form-content />` tag. This tag will be replaced by form content and rest of the inner html of `abp-dynamic-form` tag will be unchanged.
Usage:
````xml
<abp-dynamic-form abp-model="@Model.MyExampleModel">
<div>
Some content....
</div>
<div class="input-area">
<abp-form-content />
</div>
<div>
Some more content....
</div>
</abp-dynamic-form>
````
## Input Order
`abp-dynamic-form` orders the properties by their `DisplayOrder` attribute and then their property order in model class.
Default `DisplayOrder` attribute number is 10000 for every property.
See example below:
````csharp
public class OrderExampleModel
{
[DisplayOrder(10004)]
public string Name{ get; set; }
[DisplayOrder(10005)]
public string Surname{ get; set; }
//Default 10000
public string EmailAddress { get; set; }
[DisplayOrder(10003)]
public string PhoneNumber { get; set; }
[DisplayOrder(9999)]
public string City { get; set; }
}
````
In this example, input fields will be displayed with this order: `City` > `EmailAddress` > `PhoneNumber` > `Name` > `Surname`.
## Ignoring a property
By default, `abp-dynamic-form` generates input for every property in model class. If you want to ignore a property, use `DynamicFormIgnore` attribute.
See example below:
````csharp
public class MyModel
{
public string Name { get; set; }
[DynamicFormIgnore]
public string Surname { get; set; }
}
````
In this example, no input will be generated for `Surname` property.
## Indicating Text box, Radio Group and Combobox
If you have read the [Form elements document](Form-elements.md), you noticed that `abp-radio` and `abp-select` tags are very similar on c# model. So we have to use `[AbpRadioButton()]` attribute to tell `abp-dynamic-form` which of your properties will be radio group and which will be combobox. See example below:
````xml
<abp-dynamic-form abp-model="@Model.MyDetailedModel"/>
````
Model:
````csharp
public class DynamicFormsModel : PageModel
{
[BindProperty]
public DetailedModel MyDetailedModel { get; set; }
public List<SelectListItem> CountryList { get; set; } = new List<SelectListItem>
{
new SelectListItem { Value = "CA", Text = "Canada"},
new SelectListItem { Value = "US", Text = "USA"},
new SelectListItem { Value = "UK", Text = "United Kingdom"},
new SelectListItem { Value = "RU", Text = "Russia"}
};
public void OnGet()
{
MyDetailedModel = new DetailedModel
{
ComboCarType = CarType.Coupe,
RadioCarType = CarType.Sedan,
ComboCountry = "RU",
RadioCountry = "UK"
};
}
public class DetailedModel
{
public CarType ComboCarType { get; set; }
[AbpRadioButton(Inline = true)]
public CarType RadioCarType { get; set; }
[SelectItems(nameof(CountryList))]
public string ComboCountry { get; set; }
[AbpRadioButton()]
[SelectItems(nameof(CountryList))]
public string RadioCountry { get; set; }
}
public enum CarType
{
Sedan,
Hatchback,
StationWagon,
Coupe
}
}
````
As you see in example above:
* If `[AbpRadioButton()]` are used on a **Enum** property, it will be a radio group. Otherwise, combobox.
* If `[SelectItems()]` and `[AbpRadioButton()]` are used on a property, it will be a radio group.
* If just `[SelectItems()]` is used on a property, it will be a combobox.
* If none of these attributes are used on a property, it will be a text box.
## Localization
`abp-dynamic-form` handles localization as well.
By default, it will try to find "DisplayName:{PropertyName}" or "{PropertyName}" localization keys and set the localization value as input label.
You can set it yourself by using `[Display()]` attribute of Asp.Net Core. You can use a localization key in this attribute. See example below:
````csharp
[Display(Name = "Name")]
public string Name { get; set; }
````
This is not documented yet. You can see a [demo](http://bootstrap-taghelpers.abp.io/Components/DynamicForms) for now.

@ -0,0 +1,261 @@
# Form Elements
## Introduction
Abp provides form input tag helpers to make building forms easier.
## Demo
See the [form elements demo page](https://bootstrap-taghelpers.abp.io/Components/FormElements) to see it in action.
## abp-input
`abp-input` tag creates a Bootstrap form input for a given c# property. It uses [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-input-tag-helper) in background, so every data annotation attribute of `input` tag helper of Asp.Net Core is also valid for `abp-input`.
Usage:
````xml
<abp-input asp-for="@Model.MyModel.Name"/>
<abp-input asp-for="@Model.MyModel.Description"/>
<abp-input asp-for="@Model.MyModel.Password"/>
<abp-input asp-for="@Model.MyModel.IsActive"/>
````
Model:
````csharp
public class FormElementsModel : PageModel
{
public SampleModel MyModel { get; set; }
public void OnGet()
{
MyModel = new SampleModel();
}
public class SampleModel
{
[Required]
[Placeholder("Enter your name...")]
[InputInfoText("What is your name?")]
public string Name { get; set; }
[Required]
[FormControlSize(AbpFormControlSize.Large)]
public string SurName { get; set; }
[TextArea(Rows = 4)]
public string Description { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public bool IsActive { get; set; }
}
}
````
### Attributes
You can set some of the attributes on your c# property, or directly on html tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes.
#### Property Attributes
- `[TextArea()]`: Converts the input into a text area.
* `[Placeholder()]`: Sets placeholder for input. You can use a localization key directly.
* `[InputInfoText()]`: Sets a small info text for input. You can use a localization key directly.
* `[FormControlSize()]`: Sets size of form-control wrapper element. Available values are
- `AbpFormControlSize.Default`
- `AbpFormControlSize.Small`
- `AbpFormControlSize.Medium`
- `AbpFormControlSize.Large`
* `[DisabledInput]` : Input is disabled.
* `[ReadOnlyInput]`: Input is read-only.
#### Tag Attributes
* `info`: Sets a small info text for input. You can use a localization key directly.
* `auto-focus`: If true, browser auto focuses on the element.
* `size`: Sets size of form-control wrapper element. Available values are
- `AbpFormControlSize.Default`
- `AbpFormControlSize.Small`
- `AbpFormControlSize.Medium`
- `AbpFormControlSize.Large`
* `disabled`: Input is disabled.
* `readonly`: Input is read-only.
* `label`: Sets the label for input.
* `display-required-symbol`: Adds the required symbol (*) to label if input is required. Default `True`.
### Label & Localization
You can set label of your input in different ways:
- You can use `Label` attribute and directly set the label. But it doesn't auto localize your localization key. So use it as `label="@L["{LocalizationKey}"].Value"`.
- You can set it using `[Display(name="{LocalizationKey}")]` attribute of Asp.Net Core.
- You can just let **abp** find the localization key for the property. It will try to find "DisplayName:{PropertyName}" or "{PropertyName}" localization keys, if `label` or `[DisplayName]` attributes are not set.
## abp-select
`abp-select` tag creates a Bootstrap form select for a given c# property. It uses [Asp.Net Core Select Tag Helper](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper) in background, so every data annotation attribute of `select` tag helper of Asp.Net Core is also valid for `abp-select`.
`abp-select` tag needs a list of `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem ` to work. It can be provided by `asp-items` attriube on the tag or `[SelectItems()]` attribute on c# property. (if you are using [abp-dynamic-form](Dynamic-forms.md), c# attribute is the only way.)
`abp-select` supports multiple selection.
`abp-select` auto-creates a select list for **Enum** properties. No extra data is needed. If property is nullable, an empty key and value is added to top of the auto-generated list.
Usage:
````xml
<abp-select asp-for="@Model.MyModel.City" asp-items="@Model.CityList"/>
<abp-select asp-for="@Model.MyModel.AnotherCity"/>
<abp-select asp-for="@Model.MyModel.MultipleCities" asp-items="@Model.CityList"/>
<abp-select asp-for="@Model.MyModel.MyCarType"/>
<abp-select asp-for="@Model.MyModel.MyNullableCarType"/>
````
Model:
````csharp
public class FormElementsModel : PageModel
{
public SampleModel MyModel { get; set; }
public List<SelectListItem> CityList { get; set; }
public void OnGet()
{
MyModel = new SampleModel();
CityList = new List<SelectListItem>
{
new SelectListItem { Value = "NY", Text = "New York"},
new SelectListItem { Value = "LDN", Text = "London"},
new SelectListItem { Value = "IST", Text = "Istanbul"},
new SelectListItem { Value = "MOS", Text = "Moscow"}
};
}
public class SampleModel
{
public string City { get; set; }
[SelectItems(nameof(CityList))]
public string AnotherCity { get; set; }
public List<string> MultipleCities { get; set; }
public CarType MyCarType { get; set; }
public CarType? MyNullableCarType { get; set; }
}
public enum CarType
{
Sedan,
Hatchback,
StationWagon,
Coupe
}
}
````
### Attributes
You can set some of the attributes on your c# property, or directly on html tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes.
#### Property Attributes
* `[SelectItems()]`: Sets the select data. Parameter should be the name of the data list. (see example above)
- `[InputInfoText()]`: Sets a small info text for input. You can use a localization key directly.
- `[FormControlSize()]`: Sets size of form-control wrapper element. Available values are
- `AbpFormControlSize.Default`
- `AbpFormControlSize.Small`
- `AbpFormControlSize.Medium`
- `AbpFormControlSize.Large`
#### Tag Attributes
- `asp-items`: Sets the select data. This Should be a list of SelectListItem.
- `info`: Sets a small info text for input. You can use a localization key directly.
- `size`: Sets size of form-control wrapper element. Available values are
- `AbpFormControlSize.Default`
- `AbpFormControlSize.Small`
- `AbpFormControlSize.Medium`
- `AbpFormControlSize.Large`
- `label`: Sets the label for input.
- `display-required-symbol`: Adds the required symbol (*) to label if input is required. Default `True`.
### Label & Localization
You can set label of your input in different ways:
- You can use `Label` attribute and directly set the label. But it doesn't auto localize your localization key. So use it as `label="@L["{LocalizationKey}"].Value".`
- You can set it using `[Display(name="{LocalizationKey}")]` attribute of Asp.Net Core.
- You can just let **abp** find the localization key for the property. It will try to find "DisplayName:{PropertyName}" or "{PropertyName}" localization keys.
Localizations of combobox values are set by `abp-select` for **Enum** property. It searches for "{EnumTypeName}.{EnumPropertyName}" or "{EnumPropertyName}" localization keys. For instance, in the example above, it will use "CarType.StationWagon" or "StationWagon" keys for localization when it localizes combobox values.
## abp-radio
`abp-radio` tag creates a Bootstrap form radio group for a given c# property. Usage is very similar to `abp-select` tag.
Usage:
````xml
<abp-radio asp-for="@Model.MyModel.CityRadio" asp-items="@Model.CityList" inline="true"/>
<abp-radio asp-for="@Model.MyModel.CityRadio2"/>
````
Model:
````csharp
public class FormElementsModel : PageModel
{
public SampleModel MyModel { get; set; }
public List<SelectListItem> CityList { get; set; } = new List<SelectListItem>
{
new SelectListItem { Value = "NY", Text = "New York"},
new SelectListItem { Value = "LDN", Text = "London"},
new SelectListItem { Value = "IST", Text = "Istanbul"},
new SelectListItem { Value = "MOS", Text = "Moscow"}
};
public void OnGet()
{
MyModel = new SampleModel();
MyModel.CityRadio = "IST";
MyModel.CityRadio2 = "MOS";
}
public class SampleModel
{
public string CityRadio { get; set; }
[SelectItems(nameof(CityList))]
public string CityRadio2 { get; set; }
}
}
````
### Attributes
You can set some of the attributes on your c# property, or directly on html tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes.
#### Property Attributes
- `[SelectItems()]`: Sets the select data. Parameter should be the name of the data list. (see example above)
#### Tag Attributes
- `asp-items`: Sets the select data. This Should be a list of SelectListItem.
- `Inline`: If true, radio buttons will be in single line, next to each other. If false, they will be under each other.

@ -12,6 +12,8 @@ ABP Framework also adds some **useful features** to the standard bootstrap compo
Here, the list of components those are wrapped by the ABP Framework:
* [Form Elements](Form-elements.md)
* [Dynamic-Forms](Dynamic-Forms.md)
* [Buttons](Buttons.md)
* [Cards](Cards.md)
* [Alerts](Alerts.md)

Loading…
Cancel
Save