« Blazor ASP.NET Core 6.0 » : différence entre les versions
De Banane Atomic
Aller à la navigationAller à la recherche
Ligne 302 : | Ligne 302 : | ||
<filebox fn='Pages/MyPage.razor.cs'> | <filebox fn='Pages/MyPage.razor.cs'> | ||
[Inject] | [Inject] | ||
public IJSRuntime | public IJSRuntime JS { get; set; } | ||
await | // one way to import mypage.js | ||
var result = await | await JS.InvokeVoidAsync("import", "./js/mypage.js"); | ||
await JS.InvokeVoidAsync("MyJSMethod", "arg1"); | |||
var result = await JS.InvokeAsync<string>("AddExclamationPoint", "arg1"); | |||
</filebox> | </filebox> | ||
<filebox fn='wwwroot/js/ | <filebox fn='wwwroot/js/mypage.js'> | ||
window.MyJsMethod = function(arg1) { | window.MyJsMethod = function(arg1) { | ||
alert(arg1); | alert(arg1); | ||
Ligne 318 : | Ligne 321 : | ||
</filebox> | </filebox> | ||
Another way to import mypage.js | |||
<filebox fn='Pages/_Host.cshtml'> | <filebox fn='Pages/_Host.cshtml'> | ||
<body> | <body> | ||
@* | @* at the end of body *@ | ||
<script src="js/ | <script src="js/mypage.js"></script> | ||
</body> | </body> | ||
</filebox> | </filebox> |
Version du 23 janvier 2022 à 23:30
Links
Create a new app
# Blazor server dotnet new blazorserver -o [project-name] --no-https cd [project-name] dotnet run |
Solution Blazor / Webapi
# create item/item.sln dotnet new sln -o item cd item dotnet new blazorserver -o item.blazor --no-https dotnet new webapi -o item.webapi --no-https dotnet sln add item.blazor/item.blazor.csproj dotnet sln add item.webapi/item.webapi.csproj |
item/.vscode/tasks.json |
{ "version": "2.0.0", "tasks": [ { "label": "build blazor", "command": "dotnet", "type": "process", "args": [ "build", "${workspaceFolder}/item.blazor/item.blazor.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "build webapi", "command": "dotnet", "type": "process", "args": [ "build", "${workspaceFolder}/item.webapi/item.webapi.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "build all", "dependsOn": [ "build blazor", "build webapi" ], "group": "build", "problemMatcher": [] } ] } |
item/.vscode/launch.json |
{ "version": "0.2.0", "configurations": [ { "name": "blazor", "type": "coreclr", "request": "launch", "preLaunchTask": "build blazor", "program": "${workspaceFolder}/item.blazor/bin/Debug/net6.0/item.blazor.dll", "args": [], "cwd": "${workspaceFolder}/item.blazor", "stopAtEntry": false, "serverReadyAction": { "action": "openExternally", "pattern": "\\bNow listening on:\\s+(https?://\\S+)" }, "env": { "ASPNETCORE_ENVIRONMENT": "Development" }, "sourceFileMap": { "/Views": "${workspaceFolder}/Views" } }, { "name": "webapi", "type": "coreclr", "request": "launch", "preLaunchTask": "build webapi", "program": "${workspaceFolder}/item.webapi/bin/Debug/net6.0/item.webapi.dll", "args": [], "cwd": "${workspaceFolder}/item.webapi", "stopAtEntry": false, "serverReadyAction": { "action": "openExternally", "pattern": "\\bNow listening on:\\s+(https?://\\S+)" }, "env": { "ASPNETCORE_ENVIRONMENT": "Development" }, "sourceFileMap": { "/Views": "${workspaceFolder}/Views" } } ], "compounds": [ { "name": "blazor / webapi", "configurations": [ "blazor", "webapi" ], "preLaunchTask": "build all" } ] } |
Pages
Pages/Items.razor |
@* url *@ @page "/items" @* url with a parameter *@ @page "/item/{id:int}" <PageTitle>Items</PageTitle> @* wait for the Items to be loaded *@ @if (items == null) { <p><em>Loading...</em></p> } else { /* ... */ } |
Pages/Items.razor.cs |
public partial class Items : ComponentBase { private IReadOnlyCollection<ItemDto> items; [Parameter] public int Id { get; set; } protected override async Task OnInitializedAsync() { items = await this.ItemClient.GetAsync(); } } |
CSS isolation
Pages/Items.razor.css |
/* scoped css only for this page */ /* @import is not allowed in scoped css */ |
Static files
Pages/_Layout.cshtml |
<head> <link href="css/site.css" rel="stylesheet" /> <link href="{AssemblyName}.styles.css" rel="stylesheet" /> @* active CSS isolation *@ |
wwwroot/css/site.css |
/* only CSS for the entire app, not a specific page */ |
- wwwroot/favicon.ico
LibMan
LibMan is a library manager
# install the LibMan CLI dotnet tool install -g Microsoft.Web.LibraryManager.Cli # create a libman.js file libman init # available providers: cdnjs, jsdelivr, unpkg, filesystem # install bootstrap, only bootstrap.min.css and bootstrap.bundle.min.js libman install bootstrap@5.0.1 --files dist/css/bootstrap.min.css --files dist/js/bootstrap.bundle.min.js # default destination path: wwwroot/lib/bootstrap libman install bootswatch@5.0.1 --files dist/darkly/bootstrap.min.css # uninstall bootstrap libman uninstall bootstrap@5.0.1 |
Data binding
One way
Changes made in the UI doesn't change the binded property.
The onchange event can be used to manually update the property.
Fichier:Blazor.svg | <input type="text" value="@Description" @onchange=@((ChangeEventArgs __e) => Description = __e.Value.ToString()) @onchange=OnInputChanged /> @code { string Description { get; set; } = "Text"; void OnInputChanged(ChangeEventArgs e) => Description = e.Value.ToString(); } |
Two way
Fichier:Blazor.svg | @* by default uses the on change event (focus lost) *@ <input type="text" @bind=Description /> @* change to on input event *@ <input type="text" @bind=Description @bind:event="oninput" /> @code { string Description { get; set; } = "Text"; } |
Form
EditItem.razor |
@page "/edititem/{ItemId:int}" @* to access to Model.Item *@ @using Model <EditForm Model="@item" OnValidSubmit="@HandleValidSubmitAsync" OnInvalidSubmit="@HandleInvalidSubmitAsync"> <button type="submit">Save</button> <button @onclick="Cancel">Cancel</button> </EditForm> |
EditItem.razor.cs |
[Parameter] public int ItemId { get; set; } [Inject] private IItemDataService ItemDataService { get; set; } private Item item = new Item(); protected override async Task OnInitializedAsync() { item = await ItemDataService.GetItemAsync(ItemId); } // when the submit button is clicked and the model is valid private async Task HandleValidSubmitAsync() { await ItemDataService.UpdateItemAsync(item); } // when the submit button is clicked and the model is not valid private async Task HandleInvalidSubmitAsync() { } |
Input Checkbox
InputCheckbox requires a cascading parameter of type EditContext. For example, you can use InputCheckbox inside an EditForm. |
<div class="form-group row"> <label for="smoker" class=" offset-sm-3"> <InputCheckbox id="smoker" @bind-Value="Employee.Smoker"> </InputCheckbox> Smoker </label> </div> |
To have a checkbox without an EditForm use input type="checkbox" instead:
<label> <input type="checkbox" @onchange=OnCheckboxValueChanged /> Text ... </label> @code { private void OnCheckboxValueChanged(ChangeEventArgs e) { var checkboxValue = (bool)e.Value; } } |
Javascript interop
Call JS from .NET
Pages/MyPage.razor.cs |
[Inject] public IJSRuntime JS { get; set; } // one way to import mypage.js await JS.InvokeVoidAsync("import", "./js/mypage.js"); await JS.InvokeVoidAsync("MyJSMethod", "arg1"); var result = await JS.InvokeAsync<string>("AddExclamationPoint", "arg1"); |
wwwroot/js/mypage.js |
window.MyJsMethod = function(arg1) { alert(arg1); } window.AddExclamationPoint = function(arg1) { return arg1 + ' !'; } |
Another way to import mypage.js
Pages/_Host.cshtml |
<body> @* at the end of body *@ <script src="js/mypage.js"></script> </body> |
Call .NET from JS
wwwroot/js/site.js |
window.UpdateButtonContent = function (dotnetHelper, newContent) { dotnetHelper.invokeMethodAsync('UpdateButtonContent', newContent); dotnetHelper.dispose(); }; |
Pages/MyPageBase.cs |
var objRef = DotNetObjectReference.Create(this); await JSRuntime.InvokeVoidAsync("UpdateButtonContentJS", objRef, newContent); objRef.Dispose(); [JSInvokable] public void UpdateButtonContent(string newContent) { ButtonContent = newContent; } |
Pages/_Host.cshtml |
<body> @* à la fin de body *@ <script src="js/myscript.js"></script> </body> |