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.

277 lines
9.3 KiB

---
sidebar_position: 2
title: Page creation
---
## Creation of a new page
In order to display your data, we will create a new page.
To do this, nothing could be simpler, select the `Pages` folder then right click and select `Add > Razor Component...`
![Creation of a new page](/img/affichage-donnees/creation-page-01.png)
We will name our page `List.razor` then click on `Add`
![Creation of a new page](/img/affichage-donnees/creation-page-02.png)
## Separation View & Model
In order to separate the View and Model part, we will therefore create a partial class for our view.
Select the `Pages` folder then right click and select `Add > Class...`
![Separation View & Model](/img/affichage-donnees/creation-page-03.png)
We will name our class `List.razor.cs` then click on `Add`
![Separation View & Model](/img/affichage-donnees/creation-page-04.png)
Remember to make your class partial with the `partial` keyword as follows:
```csharp title="Pages/List.razor.cs"
public partial class List
{
}
```
You can now remove the code from your view, for that remove the following part:
```cshtml title="Pages/List.razor"
<h3>List</h3>
// highlight-start
@code {
}
// highlight-end
```
## Declare the url of our new page
In order to make our page accessible, let's declare the url of our page as follows:
```cshtml title="Pages/List.razor"
// highlight-next-line
@page "/list"
<h3>List</h3>
```
From now on our page will be available from the `/list` address of our site.
## Add our new page to the menu
Open the `Shared/NavMenu.razor` file and add the highlighted lines:
```cshtml title="Shared/NavMenu.razor"
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">TO_DELETE_BlazorApp30000</a>
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column">
// highlight-start
<div class="nav-item px-3">
<NavLink class="nav-link" href="list" Match="NavLinkMatch.All">
<span class="oi oi-list-rich" aria-hidden="true"></span> List
</NavLink>
</div>
// highlight-end
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</NavLink>
</div>
</nav>
</div>
@code {
private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}
```
You can now navigate to your new page.
## Concept: Layout
Some app elements, such as menus, copyright messages, and company logos, are usually part of the overall app layout.
Placing a copy of the markup for these elements in all components of an application is not efficient.
Whenever one of these elements is updated, every component that uses the element must be updated.
This approach is expensive to maintain and can lead to inconsistent content if an update is missed.
Layouts solve these problems.
### Create a layout
To create a layout:
* Create a new Razor component. Layouts use the `.razor` extension like regular Razor components. Since layouts are shared between components of an application, they are usually placed in the `Shared` application folder. However, layouts can be placed anywhere accessible to components that use it.
* Inherits the component from `LayoutComponentBase`, it defines a `Body` property (type `RenderFragment`) so that the content is rendered inside the layout.
* Use the Razor `@Body` syntax to specify the location in the layout tag where the content is displayed.
* The following `DoctorWhoLayout` layout shows a sample layout. The layout inherits from `LayoutComponentBase` and defines the `@Body` between the navbar ( &lt;nav&gt;...&lt;/nav&gt; ) and the footer ( &lt;footer&gt;...&lt;/footer&gt; ; ).
```cshtml title="Shared/DoctorWhoLayout.razor"
// highlight-next-line
@inherits LayoutComponentBase
<header>
<h1>Doctor Who&trade; Episode Database</h1>
</header>
<nav>
<a href="masterlist">Master Episode List</a>
<a href="search">Search</a>
<a href="new">Add Episode</a>
</nav>
// highlight-next-line
@Body
<footer>
@TrademarkMessage
</footer>
@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/";
}
```
### Apply a layout
Use the Razor `@layout` directive to apply a layout to a Razor routable component that has an `@page` directive.
The compiler converts `@layout` to a `LayoutAttribute` and applies the attribute to the component class.
The content of the next `Episodes` page is inserted into the `DoctorWhoLayout` at the position of `@Body`.
```cshtml title="Pages/Episodes.razor"
@page "/episodes"
// highlight-next-line
@layout DoctorWhoLayout
<h2>Episodes</h2>
<ul>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfknq">
<em>The Ribos Operation</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfdsb">
<em>The Sun Makers</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vhc26">
<em>Nightmare of Eden</em>
</a>
</li>
</ul>
```
The following rendered HTML markup is produced by the `DoctorWhoLayout` layout and the `Episodes` page. Superfluous markup does not appear in order to focus on the content provided by the two components involved:
* The Doctor Who episode database ™ header ( &lt;h1&gt;...&lt;/h1&gt; ) of the header ( &lt;header&gt;...&lt;/header&gt; ), of the navigation bar ( &lt;nav&gt;...&lt;/nav&gt; ) and the trademark information element ( &lt;div&gt;...&lt;/div&gt; ) of the footer ( &lt; footer&gt;...&lt;/footer&gt; ) comes from the `DoctorWhoLayout` component.
* The episodes header ( &lt;h2&gt;...&lt;/h2&gt; ) and episode list ( &lt;ul&gt;...&lt;/ul&gt; ) come from the `Episodes` page.
```cshtml
<body>
<div id="app">
<header>
<h1>Doctor Who&trade; Episode Database</h1>
</header>
<nav>
<a href="main-list">Main Episode List</a>
<a href="search">Search</a>
<a href="new">Add Episode</a>
</nav>
<h2>Episodes</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<footer>
Doctor Who is a registered trademark of the BBC.
https://www.doctorwho.tv/
</footer>
</div>
</body>
```
### Apply a layout to a component folder
Each application folder can optionally contain a template file named `_Imports.razor`.
The compiler includes the directives specified in the `Imports` file in all Razor templates in the same folder and recursively in all its subfolders.
Therefore, a `_Imports.razor` file containing `@layout DoctorWhoLayout` ensures that all components in a folder use the `DoctorWhoLayout` layout.
There is no need to repeatedly add `@layout DoctorWhoLayout` to all Razor Components ( .razor ) in the folder and subfolders.
:::caution
Do not add a Razor `@layout` directive to the root `_Imports.razor` file, which results in an infinite layout loop.
To control the default application layout, specify the layout in the `Router` component.
:::
:::note
The Razor `@layout` directive only applies a layout to routable components with a `@page` directive.
:::
Example :
My application contains its pages in the `Pages` folder, I want to add an administration part to my application so I will create an `Admin` directory in the `Pages` folder:
![Apply a layout to a component folder](/img/affichage-donnees/layout-01.png)
I created a layout for my admin part located `Shared/AdminLayout.razor` and I want my admin pages to use it, two choices:
* Add at the top of each page `@layout AdminLayout`
* This choice is not the most relevant because in the event of a change of layout, you will have to go back to all the pages
* Create a `_Imports.razor` file and specify `@layout AdminLayout`, all pages in my `Admin` folder will now use this layout.
### Apply a default layout to an app
Specify the default application layout in the `App` component of the `Router` component.
The following example from an app based on a Blazor project template sets the default layout to the `MainLayout` layout.
```cshtml title="App.razor"
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<p>Sorry, there's nothing at this address.</p>
</NotFound>
</Router>
```
### Nested Layouts
A component can refer to a layout which, in turn, refers to another layout. For example, nested layouts are used to create multilevel menu structures.