From 3d68628e3d28b249934dced02430b05d4cbe78f5 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 4 Sep 2020 12:18:04 +0100 Subject: [PATCH 1/5] Update JS interop to use auto-loaded ES6 module --- .../ExampleJsInterop.cs | 34 +++++++++++++++---- .../wwwroot/exampleJsInterop.js | 12 +++---- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs index 4e5efbbcdf0f..f7b80a6548eb 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs @@ -1,16 +1,36 @@ -using Microsoft.JSInterop; +using System; using System.Threading.Tasks; +using Microsoft.JSInterop; namespace Company.RazorClassLibrary1 { - public class ExampleJsInterop + // This class provides an example of how JavaScript functionality can be wrapped + // in a .NET class for easy consumption. The associated JavaScript module is + // loaded on demand when the class is instantiated. + // + // This class can be registered as scoped DI service and then injected into Blazor + // components for use. + + public class ExampleJsInterop : IAsyncDisposable { - public static ValueTask Prompt(IJSRuntime jsRuntime, string message) + private readonly Task moduleTask; + + public ExampleJsInterop(IJSRuntime jsRuntime) + { + moduleTask = jsRuntime.InvokeAsync( + "import", "./_content/Company.RazorClassLibrary1/exampleJsInterop.js").AsTask(); + } + + public async ValueTask Prompt(string message) + { + var module = await moduleTask; + return await module.InvokeAsync("showPrompt", message); + } + + public async ValueTask DisposeAsync() { - // Implemented in exampleJsInterop.js - return jsRuntime.InvokeAsync( - "exampleJsFunctions.showPrompt", - message); + var module = await moduleTask; + await module.DisposeAsync(); } } } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js index e35d0744fb35..ea8d76ad2d12 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/wwwroot/exampleJsInterop.js @@ -1,8 +1,6 @@ -// This file is to show how a library package may provide JavaScript interop features -// wrapped in a .NET API +// This is a JavaScript module that is loaded on demand. It can export any number of +// functions, and may import other JavaScript modules if required. -window.exampleJsFunctions = { - showPrompt: function (message) { - return prompt(message, 'Type anything here'); - } -}; +export function showPrompt(message) { + return prompt(message, 'Type anything here'); +} From b302bc2c4ae0d6cfd4f57ca5606f9f238f3fc09d Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 4 Sep 2020 12:32:01 +0100 Subject: [PATCH 2/5] Test update --- src/ProjectTemplates/test/template-baselines.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/test/template-baselines.json b/src/ProjectTemplates/test/template-baselines.json index e77037842c72..ac99c7a49167 100644 --- a/src/ProjectTemplates/test/template-baselines.json +++ b/src/ProjectTemplates/test/template-baselines.json @@ -877,9 +877,9 @@ "Files": [ "wwwroot/background.png", "wwwroot/exampleJsInterop.js", - "wwwroot/styles.css", "_Imports.razor", "Component1.razor", + "Component1.razor.css", "ExampleJsInterop.cs" ] }, From e288853c0a4cd2acbfc9f79bc8d8061720e4c043 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 4 Sep 2020 16:07:05 +0100 Subject: [PATCH 3/5] Make it lazy for compatibility with prerendering --- .../RazorClassLibrary-CSharp/ExampleJsInterop.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs index f7b80a6548eb..c4cb10c3205c 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs @@ -13,24 +13,27 @@ namespace Company.RazorClassLibrary1 public class ExampleJsInterop : IAsyncDisposable { - private readonly Task moduleTask; + private readonly Lazy> moduleTask; public ExampleJsInterop(IJSRuntime jsRuntime) { - moduleTask = jsRuntime.InvokeAsync( - "import", "./_content/Company.RazorClassLibrary1/exampleJsInterop.js").AsTask(); + moduleTask = new (async () => await jsRuntime.InvokeAsync( + "import", "./_content/Company.RazorClassLibrary1/exampleJsInterop.js")); } public async ValueTask Prompt(string message) { - var module = await moduleTask; + var module = await moduleTask.Value; return await module.InvokeAsync("showPrompt", message); } public async ValueTask DisposeAsync() { - var module = await moduleTask; - await module.DisposeAsync(); + if (moduleTask.IsValueCreated) + { + var module = await moduleTask.Value; + await module.DisposeAsync(); + } } } } From 40ca1eb84bff755696d0f7b506ac7ff6d6261b6d Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 4 Sep 2020 16:11:29 +0100 Subject: [PATCH 4/5] Update comment --- .../content/RazorClassLibrary-CSharp/ExampleJsInterop.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs index c4cb10c3205c..faeef6ab5461 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs @@ -6,7 +6,7 @@ namespace Company.RazorClassLibrary1 { // This class provides an example of how JavaScript functionality can be wrapped // in a .NET class for easy consumption. The associated JavaScript module is - // loaded on demand when the class is instantiated. + // loaded on demand when first needed. // // This class can be registered as scoped DI service and then injected into Blazor // components for use. From 6bc0978422c326c57b0e5b5370313c5805c3e89f Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 4 Sep 2020 16:13:51 +0100 Subject: [PATCH 5/5] Code style: go back to .AsTask - it's probably easier to read --- .../content/RazorClassLibrary-CSharp/ExampleJsInterop.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs index faeef6ab5461..769455838f24 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs @@ -17,8 +17,8 @@ public class ExampleJsInterop : IAsyncDisposable public ExampleJsInterop(IJSRuntime jsRuntime) { - moduleTask = new (async () => await jsRuntime.InvokeAsync( - "import", "./_content/Company.RazorClassLibrary1/exampleJsInterop.js")); + moduleTask = new (() => jsRuntime.InvokeAsync( + "import", "./_content/Company.RazorClassLibrary1/exampleJsInterop.js").AsTask()); } public async ValueTask Prompt(string message)