最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Blazor enable dynamic root componentsError: Dynamic root components have not been enabled in this application - Sta

programmeradmin1浏览0评论

I want render a Blazor ponent from javascript. See / "Render Blazor ponents from JavaScript"

I have a HTML file:

<script src="/_framework/blazor.server.js"></script>
<div id="counter"></div>

<script>
    async function ready() {
        let containerElement = document.getElementById('counter');
        await Blazor.rootComponents.add(containerElement, 'counter', { incrementAmount: 10 });
    }
    document.addEventListener("DOMContentLoaded", ready);
</script>

And do

builder.Services.AddServerSideBlazor(options =>
{
    options.RootComponents.RegisterForJavaScript<Counter>("counter");
});

Error message (JavaScript):

test.html:14 Uncaught (in promise) Error: Dynamic root ponents have not been enabled in this application.
    at E (blazor.server.js:1)
    at Object.add (blazor.server.js:1)
    at HTMLDocument.ready (test.html:8)

How can i enable dynamic root ponents?

I want render a Blazor ponent from javascript. See https://devblogs.microsoft./aspnet/asp-net-core-updates-in-net-6-rc-1/ "Render Blazor ponents from JavaScript"

I have a HTML file:

<script src="/_framework/blazor.server.js"></script>
<div id="counter"></div>

<script>
    async function ready() {
        let containerElement = document.getElementById('counter');
        await Blazor.rootComponents.add(containerElement, 'counter', { incrementAmount: 10 });
    }
    document.addEventListener("DOMContentLoaded", ready);
</script>

And do

builder.Services.AddServerSideBlazor(options =>
{
    options.RootComponents.RegisterForJavaScript<Counter>("counter");
});

Error message (JavaScript):

test.html:14 Uncaught (in promise) Error: Dynamic root ponents have not been enabled in this application.
    at E (blazor.server.js:1)
    at Object.add (blazor.server.js:1)
    at HTMLDocument.ready (test.html:8)

How can i enable dynamic root ponents?

Share Improve this question asked Sep 24, 2021 at 17:44 XeddonXeddon 4499 silver badges24 bronze badges 1
  • I'm running into this as well. I'll try to share it to see if anyone can help us. In case anyone wants a sample, this is for Blazor WASM, but same error: github./Swimburger/RenderBlazorFromJs – Swimburger Commented Sep 28, 2021 at 4:18
Add a ment  | 

1 Answer 1

Reset to default 9

The error is happening because of the delay between the document loading and Blazor being "ready" to process your request to add a ponent.

There doesn't appear to be any official documented solution for this, but something like this is possible

Change Blazor to manual start:

index.html

<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script src="js/script.js" defer></script>

Start Blazor, then try to add ponents - repeat until success

script.js

document.addEventListener("DOMContentLoaded", startBlazor)

function startBlazor() {
    Blazor
        .start()
        .then(() => {
            requestAnimationFrame(AddBlazorComponents)
        })
        .catch((error) => console.error(error));
}

let attempts = 0
const maxAttempts = 120 // arbitrary choice

function AddBlazorComponents() {
    if (attempts > maxAttempts) {
        // give up after trying too many times
        console.error("Could not load Blazor ponents.")
        return
    }

    const containerElement = document.querySelector('#app')
    Blazor.rootComponents.add(containerElement, 'app', {})
        .catch(reason => {
            if (reason.message === "Dynamic root ponents have not been enabled in this application.")
                requestAnimationFrame(AddBlazorComponents)
            else
                console.error(reason)
        })
    attempts++
}

Better solution?

You could, possibly, add a JSInterop call to your .NET code to facilitate this, after the application starts - but it would be different for the different hosting models : Blazor Server / Blazor WebAssembly.

Even better might be to make a PR to the aspnetcore repo with a method of pre-registering ponents for the framework to load when it is ready.

Update 29 sep 2021

It turns out there is some currently undocumented functionality that helps here. I have copied my ment from @Swimburger 's github issue below:

The new JavaScript Initializer afterStarted is called (potentially) too soon for Dynamic ponents, but it turns out you can pass an initializer to be called for a dynamic ponent - but it is not well documented or intuitive imho.

To make this work, I changed the app startup like this (adding javaScriptInitializer: "loadApp") in program.cs:

builder.RootComponents.RegisterForJavaScript<App>(identifier: "app", javaScriptInitializer: "loadApp");

Then, and this is where it was non-intuitive, I added an export to my module (like afterStarted) called loadApp - but it wasn't called.

It turned out that loadApp is only found if I add it to the window object, so I added this to index.html

<script src="_framework/blazor.webassembly.js"></script>
<script>
    window.loadApp = function (ponent,params) {
        let containerElement = document.querySelector('#app')
        window.Blazor.rootComponents.add(containerElement, ponent, params)
    }
</script>

This feels like I am missing something in how to export my custom initializer OR it really does need to be added to window directly, which seems odd...

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论