Anto Subash.

Published on

Changing theme for your ABP app. Part 10

Table of contents

Intro

In this post we will explore how to change the theme for your ABP application..

Create an abp App and Run Migrations

Create the App

Run the following command to create the abp app.

1abp new ThemeChange

Run Migrations

change directory to src/ThemeChange.DbMigrator and run the migration project

1dotnet run

This will create the migrations and seed the data for your project.

Add the basic theme module to app

Run the following command in your solution folder.

1abp add-module Volo.BasicTheme --with-source-code --add-to-solution-file

This will add the basic theme to your solution and download the source for that theme.

Now remove the nuget package reference from the ThemeChange.Web project for Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.

Add project reference from to the Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic to the ThemeChange.Web.

Change the bootstrap theme

We are going to use the Material kit. It is a free and Open Source UI Kit for Bootstrap 4. Download the minified css from the assets/css/material-kit.min.css and place it in the wwwroot/styles/material-kit.min.css in the ThemeChange.Web

Remove the default bootstrap theme

Update the ConfigureBundle method in the BasicThemeGlobalStyleContributor in the Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic project

1public override void ConfigureBundle(BundleConfigurationContext context)
2{
3    context.Files.Add("/themes/basic/layout.css");
4    context.Files.Remove("/libs/bootstrap/css/bootstrap.css");
5}

Update the ConfigureBundles method in the ThemeChangeWebModule in the ThemeChange.Web project.

1Configure<AbpBundlingOptions>(options =>
2{
3    options.StyleBundles.Configure(
4        BasicThemeBundles.Styles.Global,
5        bundle =>
6        {
7            bundle.AddFiles("/global-styles.css");
8            bundle.AddFiles("/styles/material-kit.min.css");
9        }
10    );
11});

Changing the layout

Layouts are available in the Themes\basic\Layouts folder in the Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic project

We are going to change the Account.cshtml layout. Take a backup of that file.

Here is the updated cshtml. Based on the sample from this Signin Page

1@using Microsoft.Extensions.Localization
2@using Microsoft.Extensions.Options
3@using Volo.Abp.AspNetCore.MultiTenancy
4@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
5@using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization
6@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling
7@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.MainNavbar
8@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.PageAlerts
9@using Volo.Abp.AspNetCore.Mvc.UI.Theming
10@using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetScripts
11@using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetStyles
12@using Volo.Abp.MultiTenancy
13@using Volo.Abp.Localization
14@using Volo.Abp.Ui.Branding
15@inject IBrandingProvider BrandingProvider
16@inject IOptions<AbpMultiTenancyOptions> MultiTenancyOptions
17@inject ICurrentTenant CurrentTenant
18@inject IStringLocalizer<AbpUiMultiTenancyResource> MultiTenancyStringLocalizer
19@inject ITenantResolveResultAccessor TenantResolveResultAccessor
20
21@{
22    Layout = null;
23    var containerClass = ViewBag.FluidLayout == true ? "container-fluid" : "container"; //TODO: Better and type-safe options
24    var rtl = CultureHelper.IsRtl ? "rtl" : string.Empty;
25}
26
27<!DOCTYPE html>
28
29<html lang="@CultureInfo.CurrentCulture.Name" dir="@rtl">
30<head>
31    @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.First, StandardLayouts.Account)
32
33    <meta charset="utf-8">
34    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
35    <meta http-equiv="X-UA-Compatible" content="ie=edge">
36
37    <title>@(ViewBag.Title == null ? BrandingProvider.AppName : ViewBag.Title)</title>
38
39    @if (ViewBag.Description != null)
40    {
41        <meta name="description" content="@(ViewBag.Description as string)" />
42    }
43    <abp-style-bundle name="@BasicThemeBundles.Styles.Global" />
44      <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" rel="stylesheet" />
45    @await RenderSectionAsync("styles", false)
46
47    @await Component.InvokeAsync(typeof(WidgetStylesViewComponent))
48
49    @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Account)
50</head>
51<body class="sign-in-basic">
52  <nav class="navbar navbar-expand-lg position-absolute top-0 z-index-3 w-100 shadow-none my-3  navbar-transparent ">
53    <div class="container">
54      <a class="navbar-brand  text-white " href="/" rel="tooltip" title="Theme Change" data-placement="bottom">
55        ThemeChange
56      </a>
57      <button class="navbar-toggler shadow-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#navigation" aria-controls="navigation" aria-expanded="false" aria-label="Toggle navigation">
58        <span class="navbar-toggler-icon mt-2">
59          <span class="navbar-toggler-bar bar1"></span>
60          <span class="navbar-toggler-bar bar2"></span>
61          <span class="navbar-toggler-bar bar3"></span>
62        </span>
63      </button>
64      <div class="collapse navbar-collapse w-100 pt-3 pb-2 py-lg-0 ms-lg-12 ps-lg-5" id="navigation">
65      </div>
66    </div>
67  </nav>
68  <div class="page-header align-items-start min-vh-100" style="background-image: url('https://images.unsplash.com/photo-1497294815431-9365093b7331?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1950&q=80');" loading="lazy">
69    <span class="mask bg-gradient-dark opacity-6"></span>
70    <div class="container my-auto">
71      <div class="row">
72        <div class="col-lg-4 col-md-8 col-12 mx-auto">
73          <div class="card z-index-0 fadeIn3 fadeInBottom">
74            <div class="card-header p-0 position-relative mt-n4 mx-3 z-index-2">
75              <div class="bg-gradient-primary shadow-primary border-radius-lg py-3 pe-1">
76                <h4 class="text-white font-weight-bolder text-center mt-2 mb-0">Sign in</h4>
77                <div class="row mt-3">
78                  <div class="col-2 text-center ms-auto">
79                    <a class="btn btn-link px-3" href="javascript:;">
80                      <i class="fa fa-facebook text-white text-lg"></i>
81                    </a>
82                  </div>
83                  <div class="col-2 text-center px-1">
84                    <a class="btn btn-link px-3" href="javascript:;">
85                      <i class="fa fa-github text-white text-lg"></i>
86                    </a>
87                  </div>
88                  <div class="col-2 text-center me-auto">
89                    <a class="btn btn-link px-3" href="javascript:;">
90                      <i class="fa fa-google text-white text-lg"></i>
91                    </a>
92                  </div>
93                </div>
94              </div>
95            </div>
96            <div class="card-body">
97                @if (MultiTenancyOptions.Value.IsEnabled &&
98                  (TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true ||
99                   TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(QueryStringTenantResolveContributor.ContributorName) == true))
100                {
101                    <div class="card shadow-sm rounded mb-3">
102                        <div class="card-body px-5">
103                            <div class="row">
104                                <div class="col">
105                                    <span style="font-size: .8em;" class="text-uppercase text-muted">@MultiTenancyStringLocalizer["Tenant"]</span><br />
106                                    <h6 class="m-0 d-inline-block">
107                                        @if (CurrentTenant.Id == null)
108                                        {
109                                            <span>
110                                                @MultiTenancyStringLocalizer["NotSelected"]
111                                            </span>
112                                        }
113                                        else
114                                        {
115                                            <strong>@(CurrentTenant.Name ?? CurrentTenant.Id.Value.ToString())</strong>
116                                        }
117                                    </h6>
118                                </div>
119                                <div class="col-auto">
120                                    <a id="AbpTenantSwitchLink" href="javascript:;" class="btn btn-sm mt-3 btn-outline-primary">@MultiTenancyStringLocalizer["Switch"]</a>
121                                </div>
122                            </div>
123                        </div>
124                    </div>
125                }
126                @(await Component.InvokeAsync<PageAlertsViewComponent>())
127                @await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.First, StandardLayouts.Account)
128                @RenderBody()
129                @await Component.InvokeLayoutHookAsync(LayoutHooks.PageContent.Last, StandardLayouts.Account)
130            </div>
131          </div>
132        </div>
133      </div>
134    </div>
135    <footer class="footer position-absolute bottom-2 py-2 w-100">
136      <div class="container">
137        <div class="row align-items-center justify-content-lg-between">
138          <div class="col-12 col-md-6 my-auto">
139            <div class="copyright text-center text-sm text-white text-lg-start">
140              © <script>
141                document.write(new Date().getFullYear())
142              </script>,
143              made with <i class="fa fa-heart" aria-hidden="true"></i> by
144              <a href="https://www.creative-tim.com" class="font-weight-bold text-white" target="_blank">Creative Tim</a>
145              for a better web.
146            </div>
147          </div>
148          <div class="col-12 col-md-6">
149            <ul class="nav nav-footer justify-content-center justify-content-lg-end">
150            </ul>
151          </div>
152        </div>
153      </div>
154    </footer>
155  </div>
156    <abp-script-bundle name="@BasicThemeBundles.Scripts.Global" />
157    <script src="~/Abp/ApplicationConfigurationScript"></script>
158    <script src="~/Abp/ServiceProxyScript"></script>
159
160    @await RenderSectionAsync("scripts", false)
161    @await Component.InvokeAsync(typeof(WidgetScriptsViewComponent))
162    @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Account)
163</body>
164</html>

Repo Link: https://github.com/antosubash/ThemeChange