[Blazor] 재사용 컴포넌트 만들기
- 웹 프로그래밍/Blazor
- 2022. 11. 2. 20:25
개요
- Blazor 에서 재사용 가능한 컴포넌트 만드는 방법에 대해서 정리 진행합니다.
테스트 예제 내용
Creater.razor
컴포넌트가 있고, 해당 컴포넌트에서는 현재 EditForm 컴포넌트를 사용한 코드가 있습니다.- 예시로, EditForm 컴포넌트를 다른 컴포넌트에서도 재사용 가능하다고 가정을 하였을 때, 해당 부분을 따로 컴포넌트로 만들어서 부모 컴포넌트에서 사용 가능하도록 하는 예제 코드를 작성해 봅니다.
재사용 진행할 컴포넌트 코드
- 재사용 진행할 컴포넌트 코드 내용은 다음과 같습니다.
@if (Model is not null)
{
<EditForm Model="@Model" OnValidSubmit="FormSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="form-group">
<label class="control-label" for="FirstName">FirstName</label>
<InputText @bind-Value="Model.FirstName" id="firstname" class="form-control" placeholder="Enter FirstName" />
<ValidationMessage For="() => Model.FirstName" />
</div>
<div class="form-group">
<label class="control-label" for="LastName">LastName</label>
<InputText @bind-Value="Model.LastName" id="lastname" class="form-control" placeholder="Enter LastName" />
<ValidationMessage For="() => Model.LastName" />
</div>
<div class="form-group form-check">
<label class="form-check-label" for="IsEnrollment">
<InputCheckbox @bind-Value="Model.IsEnrollment" id="IsEnrollment" class="form-check-input" />
Is Enrollment
</label>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary"
disabled="@Busy" />
</div>
<input name="IsEnrollment" type="hidden" value="false" />
</EditForm>
}
- 위 코드는 부모 컴포넌트인
Create.razor
에서 사용중입니다. - 해당 코드를 다른 컴포넌트에서도 추후에 사용 가능하다고 판단이 되어,
EditorForm.razor
새로운 컴포넌트를 생성하고 해당 컴포넌트에 재사용 가능하도록 코드를 분리할 예정입니다. - 그럼,
EditForm.razor
컴포넌트를 생성후, 다음 코드를 추가합니다.
EditForm.razor
@using BeomBeomJoJoBlazor.Models.Candidates
@if (Model is not null)
{
<EditForm Model="@Model" OnValidSubmit="FormSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="form-group">
<label class="control-label" for="FirstName">FirstName</label>
<InputText @bind-Value="Model.FirstName" id="firstname" class="form-control" placeholder="Enter FirstName" />
<ValidationMessage For="() => Model.FirstName" />
</div>
<div class="form-group">
<label class="control-label" for="LastName">LastName</label>
<InputText @bind-Value="Model.LastName" id="lastname" class="form-control" placeholder="Enter LastName" />
<ValidationMessage For="() => Model.LastName" />
</div>
<div class="form-group form-check">
<label class="form-check-label" for="IsEnrollment">
<InputCheckbox @bind-Value="Model.IsEnrollment" id="IsEnrollment" class="form-check-input" />
Is Enrollment
</label>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary"
disabled="@Busy" />
</div>
<input name="IsEnrollment" type="hidden" value="false" />
</EditForm>
}
@code {
[Parameter]
public Candidate? Model { get; set; }
[Parameter]
public bool Busy { get; set; }
[Parameter]
public EventCallback<bool> OnSubmitCallback{ get; set; }
protected async Task FormSubmit()
{
if(OnSubmitCallback.HasDelegate)
{
await OnSubmitCallback.InvokeAsync(true);
}
}
protected async Task HandleInvalidSubmit()
{
if(OnSubmitCallback.HasDelegate)
{
await OnSubmitCallback.InvokeAsync(false);
}
}
}
EditorForm.razor
컴포넌트 코드는 위와 같습니다.- 여기서 핵심은 부모 컴포넌트에서 재사용할 코드를
EditorForm.razor
컴포넌트로 분리를 한 것입니다. - 또한, FormSubmit, HandleInvalidSubmit 과 같이 부모에서 사용하는 이벤트를 전달하기 위해서
EventCallback
속성인 OnSubmitCallback 속성을 bool 타입으로 추가하였습니다. - 이를 통해, 자식 컴포넌트에서 부모 컴포넌트로 Parameter 값을 전달할 수 있습니다.
- 다음은 부모 컴포넌트인
Create.razor
코드 입니다.
Create.razor
@page "/Candidates/Create"
@using BeomBeomJoJoBlazor.Models.Candidates
@using Microsoft.EntityFrameworkCore
@inject IDbContextFactory<CandidateAppDbContext> _ContextFactory
<PageTitle>Candidate Create</PageTitle>
<h1>Create</h1>
<hr />
@if (!String.IsNullOrEmpty(StatusMessage))
{
var statusMessageClass = StatusMessage.StartsWith("Error") ? "danger" : "sueccess";
<div class="alert alert-@statusMessageClass alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"
aria-label="Close"><span aria-hidden="true">×</span></button>
@StatusMessage
</div>
}
<div class="row">
<div class="col-md-4">
<BeomBeomJoJoBlazor.Pages.Candidates.Components.EditorForm
Model="@Model" Busy="@Busy"
OnSubmitCallback="@OnSubmitCallback">
</BeomBeomJoJoBlazor.Pages.Candidates.Components.EditorForm>
</div>
</div>
<div>
<a href="/Candidates">Back to List</a>
</div>
@code {
public Candidate? Model { get; set; }
public string? StatusMessage { get; set; }
public bool Busy { get; set; }
protected override void OnInitialized()
{
Model = new();
}
protected async Task FormSubmit()
{
// 중복 저장 방지
if(Busy)
return;
Busy = true;
try
{
if (Model is not null)
{
Model.Age = 0;
using var context = _ContextFactory.CreateDbContext();
context.Candidates.Add(Model);
await context.SaveChangesAsync();
Model = new() { IsEnrollment = Model.IsEnrollment };
StatusMessage = "Success";
}
}
catch
{
StatusMessage = "Error";
}
finally
{
Busy = false;
}
}
protected void HandleInvalidSubmit()
{
StatusMessage = string.Empty;
}
protected async Task OnSubmitCallback(bool isValid)
{
if(isValid)
{
await FormSubmit();
}
else
{
HandleInvalidSubmit();
}
}
}
- 여기서 핵심은 다음 코드 입니다.
<BeomBeomJoJoBlazor.Pages.Candidates.Components.EditorForm
Model="@Model" Busy="@Busy"
OnSubmitCallback="@OnSubmitCallback">
</BeomBeomJoJoBlazor.Pages.Candidates.Components.EditorForm>
BeomBeomJoJoBlazor.Pages.Candidates.Components.EditorForm
재사용 가능한 컴포넌트를 선언 후, 속성으로 Model, Busy, OnSubmitCallback 3개의 속성을 추가 하였습니다.- 이로써, 부모의 속성 값들이 자식 컴포넌트인
BeomBeomJoJoBlazor.Pages.Candidates.Components.EditorForm
속성 값으로 전달되어 사용할 수 있게 되었습니다. - 또한 OnSubmitCallback 메서드를 통해서 OnSubmitCallback 값에 따라 FormSubmit 메서드를 호출할 지, HandleInvalidSubmit 메서드를 호출할 지 여부도 결정할 수 있게 되었습니다.
- 이렇게 재사용 가능한 컴포넌트를 만들 수 있습니다.
728x90
'웹 프로그래밍 > Blazor' 카테고리의 다른 글
[Blazor] - 특정 페이지 ReDirection (0) | 2022.11.06 |
---|---|
[Blazor] PagIndex 속성 추가 및 Skip 과 Take 메서드로 페이징 처리 (1) | 2022.11.06 |
[Blazor] EditForm OnInvalidSubmit 속성 사용하기 (0) | 2022.10.30 |
[Blazor] Text 중복 입력 방지 (0) | 2022.10.30 |
[Blazor] EditForm에 OnValidSubmit event 사용하기 (0) | 2022.10.30 |
이 글을 공유하기