Search code examples
asp.net-coreblazorrazor-pagesblazor-webassemblyvisual-studio-mac

Add a Razor element into a RazorPage but instead of use "html" syntax I would like to add using and instance


Using the Visual Studio for Mac I created a solution with name TestBlazorWebAssemblyProgressiveNetCoreApp using the wizard and I selected the sample of WebAssembly of Blazor selecting "Hosted ASP.NET Core" and "Progressive web Application". Then I changed the NavMenu.razor with this code:

@foreach (Item item in m_Items)
{
    <div class="nav-item px-3">
        <NavLink class="nav-link" href="@item.Path" Match="NavLinkMatch.All">
            <span class="oi @item.TextStyle" aria-hidden="true"></span> @item.Title
        </NavLink>
    </div>
}

And I've added to this code to the @code section:

public class Item
{
    public ComponentBase Component { get; }
    public string Path { get; }
    public string Title { get; }
    public string TextStyle { get; }

    public Item(ComponentBase component, string path, string title, string textStyle)
    {
        Component = component;
        Path = path;
        Title = title;
        TextStyle = textStyle;
    }
}

private List<Item> m_Items = new List<Item> {
    new Item(new TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Pages.Index(), "", "Home", "oi-home"),
    new Item(new TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Pages.Counter(), "counter", "Counter", "oi-plus"),
};

public void AddItem(Item item)
{
    m_Items.Add(item);
}

Then in the MainLayout.razor, I added this code at the end:

@code {
    private NavMenu NavMenuItem {
        get
        {
            NavMenu navMenu = new NavMenu();
            //navMenu.AddItem(new TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Shared.NavMenu.Item(new TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Pages.FetchData(), "fetchdata", "Fetch data", "oi-list-rich"));
            return navMenu;
        }
    }
}

and I modify the html code commenting the <NavMenu> and adding a call to @NavMenuItem property, like this:

@NavMenuItem
<!--<NavMenu />-->

When I use the instance the menu doesn't appear (but the code of property NavMenuItem is executed). And if I use the <NavMenu /> tag, the code works fine.

I would like to know what is wrong and if there are a way to add the instance of property to the razor page like a tag.

Thanks


Solution

  • Finally, with your sugestion, I found the page of Blazor University and finaly I was be able to think up a solution to my problem. Sorry if I was a little lost with the philosofpy of Blazor/Razor, but today is the third day I was testing with this framework. I found a solution but with no instance al element in code. Instead of it I use an element with a property as parameter to pass an list of objects. Then in the object I add all elements injected in this parameter property into the property that use the razor NavMenu element to render the menu elements.

    The code in the MainLayout is:

    ...
    <NavMenu ExtraItems="ExtraItems" />
    ...
    @code {
        private List<TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Shared.NavMenu.Item> ExtraItems { get; } = new List<TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Shared.NavMenu.Item>();
        protected override void OnInitialized()
        {
            TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Shared.NavMenu.Item item = new TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Shared.NavMenu.Item(new TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Pages.FetchData(), "fetchdata", "Fetch data", "oi-list-rich");
            ExtraItems.Add(item);
            base.OnInitialized();
        }
    ...
    }
    

    And in the NavMenu is:

    ...
    <nav class="flex-column">
        @foreach (Item item in m_Items)
        {
            <div class="nav-item px-3">
                <NavLink class="nav-link" href="@item.Path" Match="NavLinkMatch.All">
                    <span class="oi @item.TextStyle" aria-hidden="true"></span> @item.Title
                </NavLink>
            </div>
        }
    </nav>
    ...
    @code {
        public class Item
        {
            public ComponentBase Component { get; }
            public string Path { get; }
            public string Title { get; }
            public string TextStyle { get; }
            
            public Item(ComponentBase component, string path, string title, string textStyle)
            {
                Component = component;
                Path = path;
                Title = title;
                TextStyle = textStyle;
            }
        }
    
        public IReadOnlyList<Item> m_ExtraItems;
        [Parameter]
        public IReadOnlyList<Item> ExtraItems
        {
            get => m_ExtraItems;
            set
            {
                m_ExtraItems = value;
                foreach(Item item in m_ExtraItems)
                {
                    AddItem(item);
                }
            }
        }
    
        private List<Item> m_Items = new List<Item> {
            new Item(new TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Pages.Index(), "", "Home", "oi-home"),
            new Item(new TestBlazorWebAssemblyProgressiveNetCoreApp.Client.Pages.Counter(), "counter", "Counter", "oi-plus"),
        };
    
        public void AddItem(Item item)
        {
            m_Items.Add(item);
        }
    }
    

    Thanks all.