Blazor 5x - قسمت یازدهم - مبانی Blazor - بخش 8 - کار با جاوا اسکریپت
نویسنده: وحید نصیری
تاریخ: ۱۳۹۹/۱۲/۱۷ ۱۵:۴۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
@page "/BlazorJS"
<h3>BlazorJS</h3>
@code
{
} <li class="nav-item px-3">
<NavLink class="nav-link" href="BlazorJS">
<span class="oi oi-list-rich" aria-hidden="true"></span> BlazorJS
</NavLink>
</li> @page "/BlazorJS"
@inject IJSRuntime JsRuntime
<h3>BlazorJS</h3>
<div class="row">
<button class="btn btn-secondary" @onclick="TestConfirmBox">Test Confirm Button</button>
</div>
<div class="row">
@if (ConfirmResult)
{
<p>Confirmation has been made!</p>
}
else
{
<p>Confirmation Pending!</p>
}
</div>
@code {
string ConfirmMessage = "Are you sure you want to click?";
bool ConfirmResult;
async Task TestConfirmBox()
{
ConfirmResult = await JsRuntime.InvokeAsync<bool>("confirm", ConfirmMessage);
}
}
dotnet tool install -g Microsoft.Web.LibraryManager.Cli libman init libman install bootstrap --provider unpkg --destination wwwroot/lib/bootstrap libman install jquery --provider unpkg --destination wwwroot/lib/jquery libman install toastr --provider unpkg --destination wwwroot/lib/toastr
<head>
<base href="~/" />
<link rel="stylesheet" href="lib/toastr/build/toastr.min.css" />
</head>
<body>
<script src="lib/jquery/dist/jquery.min.js"></script>
<script src="lib/toastr/build/toastr.min.js"></script>
<script src="_framework/blazor.server.js"></script>
</body> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<Target Name="DebugEnsureLibManEnv" BeforeTargets="BeforeBuild" Condition=" '$(Configuration)' == 'Debug' ">
<!-- Ensure libman is installed -->
<Exec Command="libman --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="libman is required to build and run this project. To continue, please run `dotnet tool install -g Microsoft.Web.LibraryManager.Cli`, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'libman'. This may take several minutes..." />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" Command="libman restore" />
</Target>
</Project> window.ShowToastr = (type, message) => {
// Toastr don't work with Bootstrap 4.2
toastr.options.toastClass = "toastr"; // https://github.com/CodeSeven/toastr/issues/599
if (type === "success") {
toastr.success(message, "Operation Successful", { timeOut: 20000 });
}
if (type === "error") {
toastr.error(message, "Operation Failed", { timeOut: 20000 });
}
}; <script src="lib/jquery/dist/jquery.min.js"></script>
<script src="lib/toastr/build/toastr.min.js"></script>
<script src="js/common.js"></script>
<script src="_framework/blazor.server.js"></script>
</body> @page "/BlazorJS"
@inject IJSRuntime JsRuntime
<div class="row">
<button class="btn btn-success" @onclick="@(()=>TestSuccess("Success Message"))">Test Toastr Success</button>
<button class="btn btn-danger" @onclick="@(()=>TestFailure("Error Message"))">Test Toastr Failure</button>
</div>
@code {
async Task TestSuccess(string message)
{
await JsRuntime.InvokeVoidAsync("ShowToastr", "success", message);
}
async Task TestFailure(string message)
{
await JsRuntime.InvokeVoidAsync("ShowToastr", "error", message);
}
}
using System.Threading.Tasks;
using Microsoft.JSInterop;
namespace BlazorServerSample.Utils
{
public static class JSRuntimeExtensions
{
public static ValueTask ToastrSuccess(this IJSRuntime JSRuntime, string message)
{
return JSRuntime.InvokeVoidAsync("ShowToastr", "success", message);
}
public static ValueTask ToastrError(this IJSRuntime JSRuntime, string message)
{
return JSRuntime.InvokeVoidAsync("ShowToastr", "error", message);
}
}
} @using BlazorServerSample.Utils
async Task TestSuccess(string message)
{
//await JsRuntime.InvokeVoidAsync("ShowToastr", "success", message);
await JsRuntime.ToastrSuccess(message);
} @inject IJSRuntime JsRuntime
@code {
// ...
public async Task TestSuccess(string message)
{
await JsRuntime.ToastrSuccess(message);
}
} @page "/ParentComponent"
<ChildComponent
OnClickBtnMethod="ShowMessage"
@ref="ChildComp"
Title="This title is passed as a parameter from the Parent Component">
<ChildContent>
A `Render Fragment` from the parent!
</ChildContent>
<DangerChildContent>
A danger content from the parent!
</DangerChildContent>
</ChildComponent>
<div class="row">
<button class="btn btn-success" @onclick="@(()=>ChildComp.TestSuccess("Done!"))">Show Alert</button>
</div>
@code {
ChildComponent ChildComp;
// ...
} @page "/js-sample"
<button class="btn btn-primary" onclick="JsFunctionHelper.invokeDotnetStaticFunction()">Invoke Static Method</button>
@code
{
[JSInvokable]
public static Task<string> HelpMessage()
{
return Task.FromResult("Help text from C# static function");
}
} window.JsFunctionHelper = {
invokeDotnetStaticFunction: function () {
DotNet.invokeMethodAsync("BlazorRazorSample.Client", "HelpMessage").then(
(data) => {
console.log(data);
}
);
}
}; @page "/js-sample"
@implements IDisposable
@inject IJSRuntime jSRuntime
<button class="btn btn-primary" @onclick="CallInstanceMethod">Invoke Instance Method</button>
@code
{
private DotNetObjectReference<JsSample> objectReference;
[JSInvokable]
public string GetAddress()
{
return "123 Main Street";
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if(firstRender)
{
objectReference = DotNetObjectReference.Create(this);
}
}
private async Task CallInstanceMethod()
{
await jSRuntime.InvokeVoidAsync("JsFunctionHelper.invokeDotnetInstanceFunction", objectReference);
}
public void Dispose()
{
objectReference?.Dispose();
}
} window.JsFunctionHelper = {
invokeDotnetInstanceFunction: function (addressProvider) {
addressProvider.invokeMethodAsync("GetAddress").then((data) => {
console.log(data);
});
}
}; آیا از روش غیر استاتیک که معرفی کردید برای این سناریو میشود استفاده کرد
<script src="assets/js/core/app-menu.js"></script> <script src="assets/js/core/app.js"></script>
export function showPrompt(message) {
return prompt(message, "Type name");
}
export function showAlert(message) {
return prompt(message, "Hello");
} @page "/js-isolation"
@inject IJSRuntime jSRuntime
<button class="btn btn-primary" @onclick="Prompt">Prompt</button>
<button class="btn btn-primary" @onclick="ShowAlert">Alert</button>
@code
{
private IJSObjectReference module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if(firstRender)
{
module = await jSRuntime.InvokeAsync<IJSObjectReference>("import", "./MyMdl.Js");
}
}
private async Task Prompt()
{
var result = await module.InvokeAsync<string>("showPrompt", "What's your name?");
}
private async Task ShowAlert()
{
await module.InvokeVoidAsync("showAlert", "Hello!");
}
} h1 {
color:red;
}
::deep h1 {
color:red;
} var timeZoneOffSet = await jsRuntime.InvokeAsync<int>("eval", "new Date().getTimezoneOffset()"); var ianaTimeZoneName = jsRuntime.Invoke<string>("eval",
"(function(){try { return ''+ Intl.DateTimeFormat().resolvedOptions().timeZone; } catch(e) {} return 'UTC';}())"); var object;
window.JsFunctionHelper = {MapSuccessResponse: function (instance, address) {
object = instance;
return instance.invokeMethodAsync("GetAddress", valuesFromApi);
}
};
function getValuesFromApi() {
.
.
.
object.invokeMethodAsync("GetAddress", valuesFromApi);
} window.setFocus = function (element) {
element.focus();
}; <input @ref="@ReferenceToInputControl" />
<input _bl_bc0f34fa-16bd-4687-a8eb-9e3838b5170d="">
private ElementReference ReferenceToInputControl;
await JSRuntime.InvokeVoidAsync("setFocus", ReferenceToInputControl); {
"compilerOptions": {
"strict": true,
"removeComments": false,
"sourceMap": false,
"noEmitOnError": true,
"target": "ES2020",
"module": "ES2020",
"outDir": "wwwroot/scripts"
},
"include": [
"Scripts/**/*.ts"
],
"exclude": [
"node_modules"
]
} <Project Sdk="Microsoft.NET.Sdk.Razor">
<ItemGroup>
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="4.3.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Content Remove="tsconfig.json" />
</ItemGroup>
<ItemGroup>
<TypeScriptCompile Include="tsconfig.json">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</TypeScriptCompile>
</ItemGroup>
</Project> window.exampleJsFunctions = {
showPrompt: function (message) {
return prompt(message, 'Type anything here');
}
}; namespace JSInteropWithTypeScript {
export class ExampleJsFunctions {
public showPrompt(message: string): string {
return prompt(message, 'Type anything here');
}
}
}
export function showPrompt(message: string): string {
var fns = new JSInteropWithTypeScript. ExampleJsFunctions();
return fns.showPrompt(message);
} private const string ScriptPath = "./_content/----namespace-here---/scripts/file.js"; private IJSObjectReference scriptModule;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (scriptModule == null)
scriptModule = await JSRuntime.InvokeAsync<IJSObjectReference>("import", ScriptPath); await scriptModule.InvokeVoidAsync("exported fn name", params); public partial class MyComponent : IAsyncDisposable
public async ValueTask DisposeAsync()
{
if (scriptModule != null)
{
await scriptModule.DisposeAsync();
}
} Blazor.addEventListener('enhancedload', () => {
// ...
});// @ts-ignore
{
"compilerOptions": {
"strict": true,
"removeComments": true,
"sourceMap": false,
"noEmitOnError": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"target": "ES2020",
"outFile": "wwwroot/scripts/app.js"
},
"include": [
"Scripts/**/*.ts"
],
"exclude": [
"node_modules"
]
}export function error(){
alert('oops, an error');
} var module = await JS.InvokeAsync<IJSObjectReference>("import", "./Panel.razor.js");
await module.InvokeVoidAsync("error"); Pages/Panel.razor Pages/Panel.razor.js Pages/Panel.razor.css
_module = await JS.InvokeAsync<IJSObjectReference>("import", "./_content/RazorClassLibrary/componentName.razor.js"); export function showPrompt(message) {
return prompt(message, 'Type anything here');
} @page "/call-js-example-6"
@implements IAsyncDisposable
@inject IJSRuntime JS
<h1>Call JS Example 6</h1>
<p>
<button @onclick="TriggerPrompt">Trigger browser window prompt</button>
</p>
<p>
@result
</p>
@code {
private IJSObjectReference? module;
private string? result;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./scripts.js");
}
}
private async Task TriggerPrompt()
{
result = await Prompt("Provide some text");
}
public async ValueTask<string?> Prompt(string message) =>
module is not null ?
await module.InvokeAsync<string>("showPrompt", message) : null;
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
await module.DisposeAsync();
}
}
} export function beforeStart(options, extensions) {
console.log("beforeStart");
}
export function afterStarted(blazor) {
console.log("afterStarted");
} <body>
...
<script src="_framework/blazor.{webassembly|server}.js"
autostart="false"></script>
<script>
Blazor.start().then(function () {
var customScript = document.createElement('script');
customScript.setAttribute('src', 'scripts.js');
document.head.appendChild(customScript);
});
</script>
</body> builder.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter");
builder.Services.AddServerSideBlazor(options =>
{
options.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter");
}); <button onclick="callCounter()">Call Counter</button>
<script>
async function callCounter() {
let containerElement = document.getElementById('my-counter');
await Blazor.rootComponents.add(containerElement, 'counter', { incrementAmount: 10 });
}
</script>
<div id="my-counter">
</div> <input @oncustompaste="HandleCustomPaste" />
<script>
Blazor.registerCustomEventType('custompaste', {
browserEventName: 'paste',
createEventArgs: event => {
// This example only deals with pasting text, but you could use arbitrary JavaScript APIs
// to deal with users pasting other types of data, such as images
return {
eventTimestamp: new Date(),
pastedData: event.clipboardData.getData('text')
};
}
});
</script> namespace BlazorCustomEventArgs.CustomEvents
{
[EventHandler("oncustompaste", typeof(CustomPasteEventArgs), enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
// This static class doesn't need to contain any members. It's just a place where we can put
// [EventHandler] attributes to configure event types on the Razor compiler. This affects the
// compiler output as well as code completions in the editor.
}
public class CustomPasteEventArgs : EventArgs
{
// Data for these properties will be supplied by custom JavaScript logic
public DateTime EventTimestamp { get; set; }
public string PastedData { get; set; }
}
} @page "/"
<p>Try pasting into the following text box:</p>
<input @oncustompaste="HandleCustomPaste" />
<p>@message</p>
@code {
string message;
void HandleCustomPaste(CustomPasteEventArgs eventArgs)
{
message = $"At {eventArgs.EventTimestamp.ToShortTimeString()}, you pasted: {eventArgs.PastedData}";
}
} error RZ9992: Script tags should not be placed inside components because they cannot be updated dynamically. To fix this, move the script tag to the 'index.html' file or another static location. For more information see https://go.microsoft.com/fwlink/?linkid=872131
<script suppress-error="BL9992" />
dotnet new blazorwasm blazor_wasm
dotnet add package Microsoft.AspNetCore.Components.CustomElements --version 0.1.0-alpha.21466.1
@page "/todo"
<PageTitle>Todo</PageTitle>
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="todo.Title" />
</li>
}
</ul>
<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>
@code {
public class TodoItem
{
public string? Title { get; set; }
public bool IsDone { get; set; }
}
private List<TodoItem> todos = new();
private string? newTodo;
private async void AddTodo(MouseEventArgs e)
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
} builder.RootComponents.RegisterAsCustomElement<Todo>("todo-element"); npx create-react-app blazor_react && cd blazor_react
<script src="_content/Microsoft.AspNetCore.Components.CustomElements/BlazorCustomElements.js"></script> <script src="_framework/blazor.webassembly.js"></script>
"proxy": "BLAZOR_APP_ADDRESS", // for example: http://localhost:5269 function App() {
return (
<div className="App">
<todo-element />
</div>
);
}
export default App;
System.InvalidOperationException: The request reached the end of the pipeline without executing the endpoint: 'BlazorWasm.WebApi.Controllers.HotelAmenityController.GetHotelAmenities (BlazorWasm.WebApi)'. Please register the EndpointMiddleware using 'IApplicationBuilder.UseEndpoints(...)' if using routing. at Microsoft.AspNetCore.Builder.ApplicationBuilder.<>c.<Build>b__18_0(HttpContext context) at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />