"how can i modify the layout from a blazor page?" Code Answer

5

state container pattern

i ended up solving this using the state container pattern.

if you don't know what that is, these links are helpful:

https://chrissainty.com/3-ways-to-communicate-between-components-in-blazor/ (last section) https://www.youtube.com/watch?v=bb4lk2kfkf0&feature=youtu.be (deeper dive with additional options)

overview

i made a scoped service just for handling nav. it's injected into my navbar component, where it is used to manage breadcrumbs. the nav service also has an event that refreshes the navbar ui whenever the breadcrumbs change.

nav options can be configured on a page-by-page basis.

to make things easier for myself, i also created a base page that inherits from componentbase.

i've simplified my code somewhat. in my actual project i am managing more than just breadcrumbs here.

mainlayout

note the navbar component in the header.

<header>
    <navbar />
</header>

<main>
     @body
</main>

navbar component

this uses the navstate component to build our breadcrumbs and handle visibility. this example uses mdbootstrap 4. in the code block at the end, we sign up for the onchange event, and we use it to re-render the component. we also implement dispose to drop that event binding, otherwise we might have memory leaks.

@inject navstate nav
@implements idisposable

<div class="subnav clearfix @(nav.visible ? "" : "invisible")">
    @*breadcrumbs*@
    <div class="float-left">
        <ol class="breadcrumb">
            @foreach (var item in nav.breadcrumbs)
            {
                if (item.active)
                {
                    <li class="breadcrumb-item active">@item.text</li>
                }
                else
                {
                    <li class="breadcrumb-item"><a href="@item.link">@item.text</a></li>
                }
            }
        </ol>
    </div>
</div>


@code {

    protected override void oninitialized()
    {
        nav.onchange += statehaschanged; 
    }

    public void dispose()
    {
        nav.onchange -= statehaschanged;
    }
}

navstate service

injected as a scoped service. in server-side blazor, scoped services exist for the lifespan of the blazor connection, so we have to be careful to reset this when a new page loads.

also worth noting: if you open multiple tabs, each tab has its own connection, so there is no chance of corruption due to one user having multiple tabs open.

public class navstate : iscopedservice
    {
        public list<breadcrumb> breadcrumbs { get; set; } = new list<breadcrumb>(); 
        public bool visible { get; set; } = false;

        public event action onchange;

        public void setvisible(bool isvisible)
        {
            visible = isvisible;
            notifystatechanged();
        }

        public void reset()
        {
            breadcrumbs = new list<breadcrumb>();
            visible = false;

            notifystatechanged();
        }

        public void setbreadcrumbs(list<breadcrumb> breadcrumbs)
        {
            breadcrumbs = breadcrumbs;
            visible = true;

            notifystatechanged();
        }

        private void notifystatechanged() => onchange?.invoke();
    }
}

the breadcrumb itself is simple:

    public class breadcrumb 
    {
        public string text { get; set; }
        public string link { get; set; }
        public bool active { get; set; }

    }

base page

    public class mypagebase : componentbase
    {
        [inject] protected navstate nav { get; set; }

        protected override void oninitialized()
        {
            // navstate (breadcrumbs, etc) is scoped, so it lives as long as our connection lives. 
            // so when a new page is visited, we need to clear navigation to prevent breadcrumbs from bleed-over, etc. 
            // this also makes the navbar invisible by default.
            nav.reset();
        }
    }

pages

with all that out of your way, on your pages, if you do nothing at all the navbar will be invisible. or you can add breadcrumbs:

        protected override async task oninitializedasync()
        {
            ...

            nav.setbreadcrumbs(new list<breadcrumb>() 
            { new breadcrumb(text: "test", link: "https://google.com" }
            );
            
            ...
        }

in my real-world implementation, i also created a fluent builder to make working with breadcrumbs a bit less clunky, but i don't want to overwhelm people.

By McHaroni on February 20 2022

Answers related to “how can i modify the layout from a blazor page?”

Only authorized users can answer the Search term. Please sign in first, or register a free account.