You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7.7 KiB

sidebar_position title
6 Creation of the form

Open the Pages/Add.razor file and edit the following file:

@page "/add"

<h3>Add</h3>

<EditForm Model="@itemModel" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <p>
        <label for="display-name">
            Display name:
            <InputText id="display-name" @bind-Value="itemModel.DisplayName" />
        </label>
    </p>
    <p>
        <label for="name">
            Name:
            <InputText id="name" @bind-Value="itemModel.Name" />
        </label>
    </p>
    <p>
        <label for="stack-size">
            Stack size:
            <InputNumber id="stack-size" @bind-Value="itemModel.StackSize" />
        </label>
    </p>
    <p>
        <label for="max-durability">
            Max durability:
            <InputNumber id="max-durability" @bind-Value="itemModel.MaxDurability" />
        </label>
    </p>
    <p>
        Enchant categories:
        <div>
            @foreach (var item in enchantCategories)
            {
                <label>
                    <input type="checkbox" @onchange="@(e => OnEnchantCategoriesChange(item, e.Value))" />@item
                </label>
            }
        </div>
    </p>
    <p>
        Repair with:
        <div>
            @foreach (var item in repairWith)
            {
                <label>
                    <input type="checkbox" @onchange="@(e => OnRepairWithChange(item, e.Value))" />@item
                </label>
            }
        </div>
    </p>
    <p>
        <label>
            Item image:
            <InputFile OnChange="@LoadImage" accept=".png" />
        </label>
    </p>
    <p>
        <label>
            Accept Condition:
            <InputCheckbox @bind-Value="itemModel.AcceptCondition" />
        </label>
    </p>

    <button type="submit">Submit</button>
</EditForm>
  • The EditForm component is rendered where the <EditForm> appears.
  • The model is created in the component code and kept in a private field ( itemModel ). The field is assigned to the Model attribute of the <EditForm> .
  • The InputText component ( id="display-name" ) is an input component for modifying string values. The @bind-Value directive attribute binds the itemModel.DisplayName model property to the Value property of the InputText component.
  • The HandleValidSubmit method is assigned to OnValidSubmit. The handler is called if the form passes validation.
  • The Data Annotations Validator (DataAnnotationsValidator) attaches support for validation using Data Annotations:
    • If the form field <input> is not populated when the Submit button is selected, an error is displayed in the validation summary (ValidationSummary) ("The DisplayName field is required.") and HandleValidSubmit is not called.
    • If the form field <input> contains more than fifty characters when the submit button is selected, an error is displayed in the validation summary ("Displayed name must not exceed 50 characters.") and HandleValidSubmit is not called.
    • If the form field <input> contains a valid value when the Submit button is selected, HandleValidSubmit is called.

Form code

Open the Pages/Add.razor.cs file and edit the following file:

public partial class Add
{
	[Inject]
	public ILocalStorageService LocalStorage { get; set; }

	[Inject]
	public IWebHostEnvironment WebHostEnvironment { get; set; }

	/// <summary>
	/// The default enchant categories.
	/// </summary>
	private List<string> enchantCategories = new List<string>() { "armor", "armor_head", "armor_chest", "weapon", "digger", "breakable", "vanishable" };

	/// <summary>
	/// The default repair with.
	/// </summary>
	private List<string> repairWith = new List<string>() { "oak_planks", "spruce_planks", "birch_planks", "jungle_planks", "acacia_planks", "dark_oak_planks", "crimson_planks", "warped_planks" };

	/// <summary>
	/// The current item model
	/// </summary>
	private ItemModel itemModel = new()
	{
		EnchantCategories = new List<string>(),
		RepairWith = new List<string>()
	};

	private async void HandleValidSubmit()
	{
		// Get the current data
		var currentData = await LocalStorage.GetItemAsync<List<Item>>("data");

		// Simulate the Id
		itemModel.Id = currentData.Max(s => s.Id) + 1;

		// Add the item to the current data
		currentData.Add(new Item
		{
			Id = itemModel.Id,
			DisplayName = itemModel.DisplayName,
			Name = itemModel.Name,
			RepairWith = itemModel.RepairWith,
			EnchantCategories = itemModel.EnchantCategories,
			MaxDurability = itemModel.MaxDurability,
			StackSize = itemModel.StackSize,
			CreatedDate = DateTime.Now
		});

		// Save the image
		var imagePathInfo = new DirectoryInfo($"{WebHostEnvironment.WebRootPath}/images");

		// Check if the folder "images" exist
		if (!imagePathInfo.Exists)
		{
			imagePathInfo.Create();
		}
		
		// Determine the image name
		var fileName = new FileInfo($"{imagePathInfo}/{itemModel.Name}.png");

		// Write the file content
		await File.WriteAllBytesAsync(fileName.FullName, itemModel.ImageContent);
		
		// Save the data
		await LocalStorage.SetItemAsync("data", currentData);
	}

	private async Task LoadImage(InputFileChangeEventArgs e)
	{
		// Set the content of the image to the model
		using (var memoryStream = new MemoryStream())
		{
			await e.File.OpenReadStream().CopyToAsync(memoryStream);
			itemModel.ImageContent = memoryStream.ToArray();
		}
	}

	private void OnEnchantCategoriesChange(string item, object checkedValue)
	{
		if ((bool)checkedValue)
		{
			if (!itemModel.EnchantCategories.Contains(item))
			{
				itemModel.EnchantCategories.Add(item);
			}

			return;
		}

		if (itemModel.EnchantCategories.Contains(item))
		{
			itemModel.EnchantCategories.Remove(item);
		}
	}

	private void OnRepairWithChange(string item, object checkedValue)
	{
		if ((bool)checkedValue)
		{
			if (!itemModel.RepairWith.Contains(item))
			{
				itemModel.RepairWith.Add(item);
			}

			return;
		}

		if (itemModel.RepairWith.Contains(item))
		{
			itemModel.RepairWith.Remove(item);
		}
	}
}

You can now add a new item, if you return to the list when your new item is present.

Concept: Form and validation

Built-in form components

The Blazor framework provides built-in form components to receive and validate user input. Inputs are validated when they are changed and when a form is submitted. The available input components are listed in the following table.

Composant dentrée Rendu comme…
InputCheckbox <input type="checkbox">
InputDate<TValue> <input type="date">
InputFile <input type="file">
InputNumber<TValue> <input type="number">
InputRadio<TValue> <input type="radio">
InputRadioGroup<TValue> Groupe denfants InputRadio<TValue>
InputSelect<TValue> <select>
InputText <input>
InputTextArea <textarea>

For more information on the InputFile component, see ASP.NET Core Blazor file uploads.

All input components, including EditForm , support arbitrary attributes. Any attribute that does not correspond to a component parameter is added to the rendered HTML element.

Input components provide the default behavior to validate when a field is changed, including updating the CSS Field class to reflect the state of the field as valid or invalid. Some components include useful parsing logic.

For example, InputDate<TValue> and InputNumber<TValue> Correctly handle unparsed values by registering unparsed values as validation errors. Types that can accept NULL values also support nullability of the target field (for example, int? for a nullable integer).