🦮 Blazor 입문
지난 시간에는 Blazor의 SPA의 개념에 대해서 상세하게 학습하는 시간을 가져보았다. SPA는 Single Page Application으로 갱신이 필요한 일부분만 갱신 처리해주는 개념이었다. 이후 Router를 통해 URI 요청이 올 경우 어떠한 컴포넌트를 보여줘야 하는지 규칙을 설정하는 것 까지 알아보았다. 이번 시간에는 Form, Validation의 개념에 대해서 학습하는 시간을 가져보며, 이 또한 직접 실습하며 페이지를 제작해보도록 한다.
🏄♀️ Form
이번 시간에는 기존에 사용하던 BlazorStudy 프로젝트를 활용하여 학습할 것이다. 이번에는 FetchData를 통해 Form을 만들고, 만든 Form을 활용하여 기존에 있던 WeatherForecast 데이터 내부에 폼을 통해 데이터를 입력하고 저장해보도록 하자.
먼저 기존의 WeatherForecastService 스크립트에서 WeatherForecast를 배열의 형태가 아닌 리스트의 형태로 변환하도록 하자.
using Microsoft.AspNetCore.Components.Routing;
namespace BlazorStudy.Data
{
public class WeatherForecastService
{
...
// List 추가
public Task<List<WeatherForecast>> GetForecastAsync(DateTime startDate)
{
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
// ToArray가 아닌 ToList로 전환
.ToList());
}
}
}
@page "/fetchdata"
...
@code {
// List로 변경
private List<WeatherForecast> _forecasts;
protected override async Task OnInitializedAsync()
{
_forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}
이 후, 데이터 추가를 위한 버튼과 버튼을 클릭하면 작동하는 AddNewForecast 함수를 설정하자.
@page "/fetchdata"
...
@if (_forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
...
<button class="btn btn-primary" @onclick="AddNewForecast">
Add New Forecast
</button>
}
@code {
private List<WeatherForecast> _forecasts;
bool _showPopup = false;
WeatherForecast _addForecast;
protected override async Task OnInitializedAsync()
{
_forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
void AddNewForecast()
{
_showPopup = true;
_addForecast = new WeatherForecast();
}
}
먼저 팝업의 활성화 여부를 설정하기 위해 _showpopup을 false로 처리하여 선언하고, 이 후 AddNewForecast함수가 실행 할 경우 _showpopup를 true로 설정하여 이 후에 있을 if-else 문에서 이를 분기하여 처리하도록 설정하자. 이 후 WeatherForecast를 _addForecast로 선언하여, 함수를 클릭할 때 마다 new를 통해 생성하여 초기화의 번거로움을 없애주도록 하자.
이 후 닫기 버튼을 클릭하여 팝업을 닫을 때 사용할 함수 ClosePopup과 데이터 저장을 위한 SaveForecast 또한 마저 설정하도록 하자.
void SaveForecast()
{
_showPopup = false;
_forecasts.Add(_addForecast);
}
void ClosePopup()
{
_showPopup = false;
}
ClosePopup은 단순하게 _showPopup을 false로 변경하여 처리하고, SaveForecast 또한 팝업을 닫기 위해 _showPopup를 false로 처리하고 이 후, _forecasts의 _addForecast 데이터를 넣어주도록 처리한다. 이제 if-else 분기를 통해 _showPopup이 true일 경우 UI를 처리하도록 하자.
@page "/fetchdata"
...
@if (_forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
...
<button class="btn btn-primary" @onclick="AddNewForecast">
Add New Forecast
</button>
if (_showPopup)
{
<div class="modal" style="display:block" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Add New Forecast</h3>
<button type="button" class="close" @onclick="ClosePopup">
<span aria-hidden="true">X</span>
</button>
</div>
<div class="modal-body">
<label for="TemperatureC">Temperature (C)</label>
<input class="form-control", type="text" placeholder="TemperatureC" @bind="_addForecast.TemperatureC"
<label for="Summary">Summary</label>
<input class="form-control", type="text" placeholder="Summary" @bind="_addForecast.Summary"
<br />
<button class="btn btn-primary" @onclick="SaveForecast">Save</button>
</div>
</div>
</div>
</div>
}
}
@code {
private List<WeatherForecast> _forecasts;
...
}
먼저 Header 영역에서는 Title을 설정해주는데, 타이틀은 <h3>~</h3>을 통해 Add New Forecas를 제목으로 설정한다. 이 후 button을 하나 만들어주어 버튼의 클릭 영역은 'X'로 설정하고 해당 버튼의 이벤트는 ClosePopup으로 설정하여 X버튼을 누를 경우 팝업을 닫는 역할을 하도록 하자.
이 후 Body 영역에서는 2개의 라벨을 설정하여 하나는 온도, 하나는 Summary를 받도록 설정하자. input class로 form-control을 설정하고 데이터는 text를 받도록 설정하자. 이후 placeholder의 설명에 각각의 기능을 작성하고, 마찬가지로 바인드 되는 함수의 내용으로는 _addForecast의 TemperatureC와 Summary를 받도록 설정하자. 이제 테스트를 위해 코드를 다 작성하고 실행해보도록 하자.
Fetch data를 클릭하면, 일기예보 하단의 Add New Forecast 버튼이 생긴 것을 볼 수 있고, 해당 버튼을 누르면 _showpopup이 true가 되어 html 영역에서 if-else 구분에서 폼이 뜨는 것을 볼 수 있다. 폼 안의 데이터는 Header의 우리가 설정해주었던 Add Forecast와 X버튼이 있는 것을 알 수 있다. 이 후 하단에는 TemperatureC와 Summary를 받는 영역이 존재한다. 이 후 Save를 누르면 우리가 설정해준 값으로 데이터가 들어가는 것을 볼 수 있다.
그러나 Date를 설정해주지 않아 0001년으로 나타나는 것을 볼 수 있다. 이를 수정하기 위해 SaveForecast 함수를 아래와 같이 수정해주도록 하자.
void SaveForecast()
{
_showPopup = false;
_addForecast.Date = DateTime.Now;
_forecasts.Add(_addForecast);
}
그러나 위와 같이 작성하면, 아무런 값을 입력하지 않아도 데이터가 입력되는 문제가 있다. 따라서 이를 수정하기 위해 validation의 과정을 추가하도록 하자.
🏄♀️ Validation
먼저, 우리가 사용하고 있는 값에 값을 입력하지 않아도 저장이 되지 않도록 검증하는 과정을 추가해야한다. 따라서 우리가 사용하는 매개변수인 TemperatureC와 Summary를 선언해준 WeatherForecast 스크립트로 돌아가 Attribute를 추가하여 힌트를 주도록 하자.
using System;
using System.ComponentModel.DataAnnotations;
namespace BlazorStudy.Data
{
public class WeatherForecast
{
public DateTime Date { get; set; }
[Required(ErrorMessage = "Need TemperatureC!")]
[Range(typeof(int), "-100", "100")]
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
[Required(ErrorMessage = "Need Summary!")]
[StringLength(10, MinimumLength = 2, ErrorMessage = "Summary must be between 2 and 10 characters.")]
public string? Summary { get; set; }
}
}
TemperatureC는 값을 입력하지 않으면 값을 입력해달라는 에러메시지와, int형 정수만 사용하도록 설정하고 값은 -100에서 100도 내로만 입력할 수 있도록 설정해준다. 이후 Summary 또한 값을 입력하지 않으면 값을 입력해달라는 에러메시지와 최대 입력 길이를 2글자에서 10글자 내외로 설정한다.
이 후 기존의 FetchData의 컴포넌트로 돌아가 modal의 body를 Razor에서 제공하는 함수인 EditForm을 통해 변경하도록 하자.
@page "/fetchdata"
...
@if (_forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
...
<button class="btn btn-primary" @onclick="AddNewForecast">
Add New Forecast
</button>
if (_showPopup)
{
<div class="modal" style="display:block" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Add New Forecast</h3>
<button type="button" class="close" @onclick="ClosePopup">
<span aria-hidden="true">X</span>
</button>
</div>
<div class="modal-body">
<EditForm Model="_addForecast" OnValidSubmit="SaveForecast">
@* Form Validation 기능 ON *@
<DataAnnotationsValidator />
@* 에러가 있으면 메시지 상세출력 *@
<ValidationSummary />
<label for="TemperatureC">Temperature (C)</label>
<InputNumber class="form-control" palceholder="TemperatureC" @bind-Value="_addForecast.TemperatureC" />"
<label for="Summary">Summary</label>
<InputText class="form-control" palceholder="Summary" @bind-Value="_addForecast.Summary" />
<br />
<button class="btn btn-primary" @onclick="SaveForecast">Save</button>
</EditForm>
</div>
</div>
</div>
</div>
}
}
@code {
private List<WeatherForecast> _forecasts;
...
}
먼저 EditForm으로 기존의 코드를 변경하도록 하자. 우리의 Model은 _addforecast이므로 해당 값을 적어주고, <DataAnnotationsValidator />를 추가로 작성하여 Form Validation 기능을 활성화 시켜주도록 하자. 해당 함수를 사용하지 않을 경우 데이터를 확인하는 과정을 거치지 않는다. 또한 해당 함수와 커플로 항상 같이 사용해야 하는 함수인 <ValidationSummary /> 또한 작성하여 에러가 발생할 때에도 해당 에러의 상세 메시지를 출력해주도록 하자. 이 후 기존의 사용하던 코드와 똑같이 동작하는 InputNumber와 InputText를 통해 데이터를 처리해주도록 하자. 마지막으로 기존과 동일하게 정상적으로 작동하는지 확인하기 위해 프로그램을 실행해보도록 하자.
이 후, 실행하여 값을 입력하지 않거나 범위 외의 값을 입력하면 에러메시지가 나타나는 것을 확인 할 수 있다. 이 후 정상적인 값을 입력하면 값을 입력하는 Form의 색상이 초록색으로 변하고 실질적으로 데이터 또한 정상적으로 저장되는 것을 확인할 수 있다.
'공부 > 인프런 - Rookiss' 카테고리의 다른 글
Part 6-5-11. Blazor 입문 : Javascript 연동 (3) | 2024.09.20 |
---|---|
Part 6-5-10. Blazor 입문 : State 관리 (0) | 2024.09.16 |
Part 6-5-8. Blazor 입문 : SPA 구조, Router (0) | 2024.09.09 |
Part 6-5-7. Blazor 입문 : Dependency Injection, Service의 종류 (3) | 2024.09.09 |
Part 6-5-6. Blazor 입문 : Templated Component (0) | 2024.09.07 |