9

Sharing Code and Resources

Throughout the book, we have been building Blazor Server and Blazor WebAssembly side by side. This is a great way to build our projects if we want to switch technologies further down the road or, as we do at work, share components between the customer portal and our internal CRM system.

Most of us will probably have one hosting model that we are working with, not usually two, but building it this way does have some perks.

Always think about if there might be a sharable part of the component we are building; that way, we can reuse it, and if we add something to the component, we get that benefit for all our components.

But it’s not only about sharing components inside our own projects. What if we want to create a library that can be shared with other departments, or even an open-source project sharing components with the world?

In this chapter, we will look at some of the things we already use when sharing components, and also at sharing CSS and other static files.

In this chapter, we will cover the following topics:

  • Adding static files
  • CSS isolation

Technical requirements

Make sure you have followed the previous chapters or use the Chapter08 folder as a starting point.

You can find the source code for this chapter’s result at https://github.com/PacktPublishing/Web-Development-with-Blazor-Second-Edition/tree/main/Chapter09.

If you are jumping into this chapter using the code from GitHub, make sure you have added Auth0 account information in the settings files. You can find the instructions in Chapter 8, Authentication and Authorization.

Adding static files

Blazor can use static files, such as images, CSS, and JavaScript. If we put our files in the wwwroot folder, they will automatically be exposed to the internet and be accessible from the root of our site. The nice thing about Blazor is that we can do the same with a library; it is super easy to distribute static files within a library.

At work, we share components between all of our Blazor projects, and the shared library can also depend on other libraries. By sharing components and building our own components (sometimes on top of other libraries), we ensure we have the same look and feel throughout a site. We also share static content like images and CSS, and this makes it simple and fast if we need to change something and we want all our sites to be affected.

To link to a resource in another library/assembly, we can use the _content folder.

Take a look at this example:

<link rel="stylesheet" href="_content/Components/MyBlogStyle.min.css" />

The HTML link tag, rel, and href are ordinary HTML tags and attributes, but adding the URL that starts with _content tells us that the content we want to access is in another library. The name of the library (assembly name), in our case Components, is followed by the file we want to access, which is stored in the wwwroot folder in our library.

Blazor is, in the end, just HTML, and HTML can be styled using CSS. As mentioned, the Blazor templates are using Bootstrap by default, and we will continue to use that as well.

There is an excellent site with easy-to-use Bootstrap themes ready to be downloaded, which can be found at https://bootswatch.com/.

I like the Darkly theme, so that’s the one we’ll use, but feel free to experiment with this later on.

Choosing between frameworks

I often get asked about how to style out Blazor apps, and the truth is you can use all the things you are used to. In the end, Blazor will output HTML. There are many languages and frameworks we can use to write our CSS.

We can use CSS, SASS, and LESS. As long as the output is CSS, we can use it.

In this chapter, we will stick with Bootstrap and continue using CSS. SASS and LESS are outside this book’s scope.

Tailwind is a popular framework for Blazor, and it is absolutely possible to use it together with Blazor. Tailwind is very component-focused and needs a bit of configuration to start, but if it is something you have worked with and like, you can use it together with Blazor.

Adding a new style

Many templates use Bootstrap as a base, so if you are looking for a design for your website, using a Bootstrap-based template will be an easy implementation.

The problem with Bootstrap (and why some people don’t like it) is that many sites use Bootstrap and “all” sites look the same. This can be good if we are building a LOB (Line of Business), but it can be bad if we are trying to be innovative. Bootstrap is also quite large when it comes to downloading, so that is also an argument against it.

This chapter is about making our blog look a bit nicer, so we will stick with Bootstrap, but we should know that if we use something else to handle our CSS, it will work with Blazor.

One of these template sites is Bootswatch, which gives us some nice variations from the traditional Bootstrap themes:

  1. Navigate to https://bootswatch.com/darkly/.
  2. In the top menu called Darkly, there are some links. Download bootstrap.min.css.
  3. In the Components project, in the wwwroot folder, add the bootstrap.min.css file.

We have all the prerequisites and CSS that we can add to our site.

Adding CSS to BlazorServer

Now it’s time to add a new style to our sites. Let’s start with BlazorServer:

  1. In the BlazorServer project, open Pages/_Host.cshtml.
  2. Replace this row:
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    

    With:

    <link rel="stylesheet" href="_content/Components/bootstrap.min.css" />
    
  1. Set BlazorServer as the startup project and run the project by pressing Ctrl + F5.

Great! Our Blazor Server project is now updated to use the new style. The main color should now be dark, but there is still some work to do.

Adding CSS to BlazorWebAssembly.Client

Now let’s do the same with the Blazor WebAssembly project:

  1. In the BlazorWebAssembly.Client project, open wwwroot/index.html.
  2. Replace this line:
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    

    With:

    <link rel="stylesheet" href="_content/Components/bootstrap.min.css" />
    
  1. Set BlazorWebAssembly.Server as the startup project and run the project by pressing Ctrl + F5.

Now we have the same layout for both projects.

Making the admin interface more usable

Let’s now clean it up some more. We have only started with the admin functionality, so let’s make it more accessible. The menu on the left is no longer required, so let’s change it so that it is only visible if you are an administrator:

  1. Open Components/Shared/MainLayout.razor and put AuthorizeView around the sidebar div like this:
    <AuthorizeView Roles="Administrator">
        <div class="sidebar">
            <NavMenu />
        </div>
    </AuthorizeView>
    

In this case, we are not specifying Authorized or NotAuthorized. The default behavior is Authorized, so if we are only looking for an authorized state, we don’t need to specify it by name.

Since this is already a shared component, we are all set. Start one of the projects (BlazorServer or BlazorWebAssembly.Server) to see it in action. The menu should not be shown if we are not logged in.

Now we need to make the menu look better. Even though the counter is really fun to click on, it doesn’t make much sense regarding our blog.

Since the nav menu is now shared, we can put it in one place, which will change for both Blazor Server and Blazor WebAssembly.

Making the menu more useful

We should replace the links with links to our admin pages instead:

  1. In the Components project, open the Shared/Navmenu.razor file.

    Edit the code so that it looks like this (keep the code block as is):

    <div class="top-row pl-4 navbar navbar-dark">
        <a class="navbar-brand" href="">MyBlog Admin</a>
        <button class="navbar-toggler" @onclick="ToggleNavMenu">
            <span class="navbar-toggler-icon"></span>    
        </button>
    </div>
    <div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
        <ul class="nav flex-column">
            <li class="nav-item px-3">
                <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                    <span class="oi oi-home" aria-hidden="true"></span> Home
                </NavLink>
            </li>
            <li class="nav-item px-3">
                <NavLink class="nav-link" href="Admin/Blogposts">
                    <span class="oi oi-signpost" aria-hidden="true"></span> Blog posts
                </NavLink>
            </li>
            <li class="nav-item px-3">
                <NavLink class="nav-link" href="Admin/Tags">
                    <span class="oi oi-tags" aria-hidden="true"></span> Tags
                </NavLink>
            </li>
            <li class="nav-item px-3">
                <NavLink class="nav-link" href="Admin/Categories">
                    <span class="oi oi-tags" aria-hidden="true"></span> Categories
                </NavLink>
            </li>
        </ul>
    </div>
    
  1. Also, remove the AuthorizeView we added; we don’t need that anymore.

Great! Our blog is looking more like a blog, but we can do more!

Making the blog look like a blog

The admin interface is done (at least, for now), and we should focus on the front page of our blog. The front page should have the title of the blog post and some descriptions.

  1. In the Components project, open the Pages/Index.razor file.
  2. Add a using statement for Markdig at the top of the file:
    @using Markdig;
    
  3. Add an OnInitializedAsync method to handle the instantiation of the Markdig pipeline (this is the same code we have in the Post.razor file):
    MarkdownPipeline pipeline;
    protected override Task OnInitializedAsync()
    {
        pipeline = new MarkdownPipelineBuilder()
                    .UseEmojiAndSmiley()
                    .Build();
        return base.OnInitializedAsync();
    }
    
  4. Inside the Virtualize component, change the content (RenderFragment) to the following:
    <Virtualize ItemsProvider="LoadPosts" Context="p">
        <article>
            <h2>@p.Title</h2>
            @((MarkupString)Markdig.Markdown.ToHtml(new string(p.Text.Take(100).ToArray()), pipeline))
            <a href="/Post/@p.Id">Read more</a>
        </article>
    </Virtualize>
    
  5. Also, remove the <ul> tags.

Now, run the project using Ctrl + F5 and look at our new front page. Our blog is starting to take form, but we still have work to do.

CSS isolation

In .NET 5, Microsoft added something called isolated CSS. This is something that many other frameworks have as well. The idea is to write CSS specifically for one component. The upsides, of course, are that the CSS that we create won’t impact any of the other components.

The template for Blazor uses isolated CSS for Components/Shared/MainLayout.razor and NavMenu.Razor. If we expand MainLayout.razor, we’ll see a file called MainLayout.razor.css.

We can also use SASS here by adding a file called MainLayout.razor.scss. The important thing is that the file we add should generate a file called MainLayout.razor.css for the compiler to pick up.

This naming convention will make sure to rewrite CSS and the HTML output.

CSS has the following naming convention:

main {
    flex: 1;
}

It will be rewritten as follows:

main[b-bfl5h5967n] {
    flex: 1;
}

This means the elements need to have an attribute called b-bfl5h5967n (in this case) for the style to be applied.

The div tag that has the CSS tag within the MainLayout component will be outputted like this:

<main b-bfl5h5967n>

For all of this to happen, we also need to have a link to the CSS (which is provided by the template), and it looks like this:

<link href="{Assemblyname}.styles.css" rel="stylesheet">

This becomes useful for component libraries. We have components that have isolated CSS in our shared library (NavMenu and MainLayout), and the CSS for the NavMenu component is included in the {Assemblyname}.styles.css file.

We don’t have to do anything extra for our shared CSS to be included. If we are creating a library for anyone to use, we should think about using the isolated CSS approach if our components need some CSS to work correctly.

If we are starting our Blazor project from an empty template, we need to add a link to the isolated CSS.

This way, our users won’t have to add a reference to our CSS, and there is no risk of our CSS breaking something in the user’s app (since it’s isolated). The important thing is that we use the right approach when it makes sense.

Suppose we are creating a component that has very specific styles, which only that component will use. In that case, isolated CSS is a great way to go, it is easier to find (right by the component), and we can use CSS variables for colors and such.

We should be careful when styling similar things inside of the isolated CSS, so we don’t end up having a bunch of different CSS files styling a button, for example.

As mentioned, the isolated CSS only affects the HTML tags inside the component, but what if we have a component inside our component?

If we open Component/Shared/NavMenu.css, we can see that for the .nav-item styles, some of them are using the keyword ::deep; this is to say that even child components should also be affected by this style.

Take a look at this code:

.nav-item ::deep a {…}

It is targeting the <a> tag, but the Razor code looks like this:

<li class="nav-item px-3">
     <NavLink class="nav-link" href="Admin/Blogposts">
         <span class="oi oi-signpost" aria-hidden="true"></span> Blog posts
     </NavLink>
</li>

It is the NavLink component that renders the <a> tag; by adding ::deep, we are saying we want to apply this style to all elements with the class .nav-item and all the <a> tags inside that element.

There is one more thing we need to know about – ::deep; it makes sure to share the ID of the attribute (b-bfl5h5967n, for example), and it needs an HTML tag to do so. So if we have a component that consists of other components (not adding any HTML tags at all), we need to add an HTML tag around the content to make ::deep work.

Before we summarize this chapter, let us do one more thing.

Let’s fix the background color of the menu:

  1. Open Components/Shared/MainLayout.razor.css.
  2. Look for the .sidebar style and replace it with:
    .sidebar {
        background-image: linear-gradient(180deg, var(--bs-body-bg) 0%,var(--bs-gray-800) 70%);
    } 
    
  3. Replace the .top-row style with:
    .top-row {
        background-color: var(--bs-primary);
        justify-content: flex-end;
        height: 3.5rem;
        display: flex;
        align-items: center;
    }
    

    We replaced the background color and removed a border.

  1. In the .top-row ::deep a, .top-row ::deep .btn-link style, add:
        color:white;
    

Now we are able to see the login/logout link a bit better.

We now have a working admin interface and a good-looking site.

Summary

In this chapter, we have moved components into a shared library and used that library with both our Blazor Server and Blazor WebAssembly projects.

Using shared libraries like this is the way to create shared libraries (for others to use), and it is also a great way to structure our in-house projects (so that it is easy to change from Blazor Server to Blazor WebAssembly, or the other way around). If you have a site already, you can build your Blazor components in a shared library, which we have done throughout the book.

Using components as part of your site (using Blazor Server), you can get started with Blazor bit by bit until you have converted the whole thing. When that is done, you can decide whether or not to keep using Blazor Server (as I mentioned, we use Blazor Server at work) or move to Blazor WebAssembly.

We talked about how we can use SASS and CSS in our site, both regular CSS and isolated CSS.

In the next chapter, we will learn about the one thing we are trying to avoid (at least I am) as Blazor developers – JavaScript.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset