# Convert Create/Edit Modals to Page
In this document we will explain how to convert BookStore's Books create & edit modals to regular blazor pages.
## Before

## After

# Books.razor Page
Books.razor page is the main page of the books management. Create & Update operations are done in this page. So we'll remove create & update operations from this page and move a separate blazor component for each operation. Each component will be a page.
- Remove both Create & Update modals.

- Replace **NewBook** button with a link to **CreateBook** page.
```html
```
- Inject `NavigationManager` to `Books.razor` page.
```csharp
@inject NavigationManager NavigationManager
```
- Replace **Edit** button with a link to **UpdateBook** page.
```html
```
```csharp
private void NavigateToEdit(Guid id)
{
NavigationManager.NavigateTo($"books/{id}/edit");
}
```
- Remove all methods in the `Books.razor` page except constructor. And add `GoToEditPage` as below:
```csharp
protected void GoToEditPage(BookDto book)
{
NavigationManager.NavigateTo($"books/{book.Id}");
}
```

- Change Edit button to a link in the table.
```html
```
# CreateBooks Page
Create new `CreateBook.razor` and `CreateBook.razor.cs` files in your project.
- `CreateBook.razor`
```html
@page "/books/new"
@attribute [Authorize(BookStorePermissions.Books.Create)]
@inherits BookStoreComponentBase
@using Acme.BookStore.Books;
@using Acme.BookStore.Localization;
@using Acme.BookStore.Permissions;
@using Microsoft.Extensions.Localization;
@using Volo.Abp.AspNetCore.Components.Web;
@inject IStringLocalizer L
@inject AbpBlazorMessageLocalizerHelper LH
@inject IBookAppService AppService
@inject NavigationManager NavigationManager
@L["NewBook"]
@L["Author"]
@L["Name"]
@L["Type"]
@L["PublishDate"]
@L["Price"]
```
- `CreateBook.razor.cs`
```csharp
using Acme.BookStore.Books;
using Blazorise;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
namespace Acme.BookStore.Blazor.Pages;
public partial class CreateBook
{
protected Validations CreateValidationsRef;
protected CreateUpdateBookDto NewEntity = new();
IReadOnlyList authorList = Array.Empty();
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
authorList = (await AppService.GetAuthorLookupAsync()).Items;
if (!authorList.Any())
{
throw new UserFriendlyException(message: L["AnAuthorIsRequiredForCreatingBook"]);
}
NewEntity.AuthorId = authorList.First().Id;
if (CreateValidationsRef != null)
{
await CreateValidationsRef.ClearAll();
}
}
protected virtual async Task CreateEntityAsync()
{
try
{
var validate = true;
if (CreateValidationsRef != null)
{
validate = await CreateValidationsRef.ValidateAll();
}
if (validate)
{
await AppService.CreateAsync(NewEntity);
NavigationManager.NavigateTo("books");
}
}
catch (Exception ex)
{
await HandleErrorAsync(ex);
}
}
}
```
# EditBooks Page
Create new `EditBook.razor` and `EditBook.razor.cs` files in your project.
- `EditBook.razor`
```html
@page "/books/{Id}"
@attribute [Authorize(BookStorePermissions.Books.Edit)]
@inherits BookStoreComponentBase
@using Acme.BookStore.Books;
@using Acme.BookStore.Localization;
@using Acme.BookStore.Permissions;
@using Microsoft.Extensions.Localization;
@using Volo.Abp.AspNetCore.Components.Web;
@inject IStringLocalizer L
@inject AbpBlazorMessageLocalizerHelper LH
@inject IBookAppService AppService
@inject NavigationManager NavigationManager
@EditingEntity.Name
@L["Author"]
@L["Name"]
@L["Type"]
@L["PublishDate"]
@L["Price"]
```
- `EditBook.razor.cs`
```csharp
using Acme.BookStore.Books;
using Blazorise;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
namespace Acme.BookStore.Blazor.Pages;
public partial class EditBook
{
protected CreateUpdateBookDto EditingEntity = new();
protected Validations EditValidationsRef;
IReadOnlyList authorList = Array.Empty();
[Parameter]
public string Id { get; set; }
public Guid EditingEntityId { get; set; }
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
// Blazor can't parse Guid as route constraint currently.
// See https://github.com/dotnet/aspnetcore/issues/19008
EditingEntityId = Guid.Parse(Id);
authorList = (await AppService.GetAuthorLookupAsync()).Items;
if (!authorList.Any())
{
throw new UserFriendlyException(message: L["AnAuthorIsRequiredForCreatingBook"]);
}
var entityDto = await AppService.GetAsync(EditingEntityId);
EditingEntity = ObjectMapper.Map(entityDto);
if (EditValidationsRef != null)
{
await EditValidationsRef.ClearAll();
}
}
protected virtual async Task UpdateEntityAsync()
{
try
{
var validate = true;
if (EditValidationsRef != null)
{
validate = await EditValidationsRef.ValidateAll();
}
if (validate)
{
await AppService.UpdateAsync(EditingEntityId, EditingEntity);
NavigationManager.NavigateTo("books");
}
}
catch (Exception ex)
{
await HandleErrorAsync(ex);
}
}
}
```
You can check the following commit for details:
https://github.com/abpframework/abp-samples/commit/aae61ad6d66ebf6191dd4dcfb4e23d30bd680a4e