MackinnonBuck / blazor-page-script

A Blazor component enabling per-page JavaScript initialization logic in statically rendered Blazor Web apps
65 stars 7 forks source link

Use PageScript to import custom functions? #4

Closed ynnob closed 7 months ago

ynnob commented 8 months ago

Hey!

I am looking for a way to add js functions on a component base to my static server rendered pages / components.

As far as i understood the docs, with the PageScript (https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/static-server-rendering?view=aspnetcore-8.0) i only can perform automatic task on load, update and dispose.

I tried adding additional functions to the component script but the added functions are not discovered when the onclick is triggered. I guess that they would need to be imported / registered also?

Component:

A.razor

<PageScript Src="./Components/Widgets/A.razor.js" />
<button onclick="TestAlert()">Click me!</button>

@code {

}

Script

A.razor.js

    export function onLoad() {
        console.log('onLoad');
    }

    export function onUpdate() {
        console.log('Updated');
    }

    export function onDispose() {
        console.log('Disposed');
    }

    function TestAlert() {
        alert('Hey whats up?!');
    }

At the end i want to avoid a big javascript file that holds every function my page needs. i would prefer adding the functions on a component base. But i am missing something here and don't really know how to add the functions at "runtime" while enhanced navigation is active.

Thanks in advance.

MackinnonBuck commented 8 months ago

Hi @ynnob, thanks for reaching out.

Unlike inline <script> tags, modules hide their top-level members (including functions) from the global scope. If you want functions defined in a JS module to be used in event attributes, you could manually attach them to the window object. Here's a basic example:

MyPage.razor

<PageScript Src="./Components/Pages/MyPage.razor.js" />
<button onclick="testAlert">Click me!</button>

MyPage.razor.js

window.testAlert = function() {
  alert('Clicked!');
};

In this case, you don't even need to define any callback functions (onLoad/onUpdate/onDispose). Top-level module code will only run once per full page load, and that's all you need to set up global state on the window object.


If you want to avoid polluting the window object with page-specific callbacks, you could group a page's functions into an object and attach that object to window:

MyPage.razor

<PageScript Src="./Components/Pages/MyPage.razor.js" />
<button onclick="myPage.testAlert">Click me!</button>

MyPage.razor.js

window.myPage = {
  testAlert: function() {
    alert('Clicked!');
  },
};

Hope this answers your question - let me know if it doesn't!

ynnob commented 7 months ago

Thanks! That made it clear.