I am working on a Blazor project in which I am using Bootstrap; which, of course, requires jQuery and Popper for the tooltips and popovers to work.
Originally, I just "manually" downloaded the required files:
- jQuery
- Popper
- Bootstrap (css and js)
and put them where they need to go:
- wwwroot/css
- wwwroot/js
The structure of wwwroot
looked like this:
/wwwroot
|
|- css/
| |
| |- bootstrap/
| |
| `- site.css
|
|- images/
|
`- js/
|
|- bootstrap/
|
|- jquery/
|
|- popper/
|
|- BootstrapJavascript.js
|
`- JavaScript.js
However, the "powers that be" have decided they would like to make this more efficient and automatic, so I now need to use LibMan to install everything, and I am using this method:
Solution Explorer -> Project -> Add -> Client-Side Library...
So, everything went smoothly when installing, however I am having trouble with Popper. After installing, wwwroot
now looks like this:
/wwwroot
|
|- css/
| |
| |- bootstrap*.*
| |
| `- site.css
|
|- images/
|
|- js/
| |
| |- bootstrap*.*
| |
| |- cjs/
| |
| |- esm/
| |
| |- umd/
| |
| `- BootstrapJavascript.js
|
`- scss/
And I am receiving errors indicating that the application cannot find certain libraries or components of libraries.
Originally, when using LibMan to install Popper, LibMan wanted to put Popper here:
wwwroot/lib/popper.js/
However, I elected to put Popper in:
wwwroot/js/
Also, on Bootstraps website, they instruct to pre-load the ability to use tooltips and popovers like this:
// For Bootstrap's Tooltips
// https://getbootstrap.com/docs/5.2/components/tooltips/
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
// For Bootstrap's Popovers
// https://getbootstrap.com/docs/5.2/components/popovers/
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
Which I have in my BootstrapJavascript.js file.
Some of the errors I am getting:
ReferenceError: exports is not defined
at https://localhost:5003/js/cjs/popper.js:7:23
Error at App.razor:line 48
, which is in here:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/cjs/popper.js"); // THIS IS LINE #48
await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/bootstrap.js");
await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/BootstrapJavaScript.js");
}
}
The application was working "perfectly" when I was hand installing Bootstrap, Popper, and jQuery, now it is not.
What do I need to do to get this working like when I was hand-installing?
EDIT:
libman.json
{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "[email protected]",
"destination": "wwwroot/js/jquery/"
},
{
"library": "[email protected]",
"destination": "wwwroot/js/popper/"
},
{
"library": "[email protected]",
"destination": "wwwroot/"
}
]
}
App.razor
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/jquery/jquery.min.js");
await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/popper/cjs/popper.min.js");
await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/bootstrap.min.js");
await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/BootstrapJavaScript.js");
}
}
_Host.cshtml:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="stylesheet" href="~/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
...
</div>
<script>
var blackpearlScript = document.createElement('script');
blackpearlScript.setAttribute('src', '/js/JavaScript.js');
document.head.appendChild(blackpearlScript);
</script>
</body>
CodePudding user response:
I tried to fully explain the general solution that I use in my projects. Probably, your problem are in the definitions of js and css entries.
First of all install LibMan
with the below command:
dotnet tool install -g Microsoft.Web.LibraryManager.Cli
The next step is to add a file called libman.json inside the project. To add this file, just enter the following command in the command prompt:
libman init
As you can see, we can also specify the package receiving source, which is set to cdnjs by default, and is actually a Content Delivery Network (CDN) for countless client-side packages. We can also enter our required packages in the libraries array. Even for each package, we can override the provider.
`{"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
]
}`
Now, you can get the Jquery, Bootstrap and so on by following command:
libman install bootstrap --provider unpkg --destination wwwroot/lib/bootstrap
libman install jquery --provider unpkg --destination wwwroot/lib/jquery
Finally, the libman.json file will have below structure:
`{"version": "1.0",
"defaultProvider": "",
"libraries": [
{
"provider": "cdnjs",
"library": "[email protected]",
"destination": "wwwroot/lib/twitter-bootstrap/"
},
{
"provider": "unpkg",
"library": "[email protected]",
"destination": "wwwroot/lib/jquery/"
}
]
}`
After receiving its client-side packages, we will add the relevant entries to the Blazor Server application's Pages \_Layout.cshtml
file (or to the Blazor WASM application's
wwwroot/index.html
file).
<head>
<base href="~/" />
<link rel="stylesheet" href="lib/twitter-
bootstrap/css/bootstrap.min.css" />
</head>
<body>
..........
..........
<script src="lib/jquery/dist/jquery.min.js"></script>
<script src="_framework/blazor.server.js"></script>
</body>
We define the entry of the css file in the head section and the js file before closing the body tag and of course before <script src="_framework/blazor.server.js"></script>
in Blazor Server. There is no need to mention the wwwroot
starting folder; Because base href
is defined, it points to this folder.
You can also use the libman restore
command to reinstall the packages; In this case, just like Nuget, the packages will be downloaded from the libman.json file from the relevant provider and added to the project.
One additional point: You can modify the program's csproj file as follows to automatically run the libman restore command before the build:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<Target Name="DebugEnsureLibManEnv" BeforeTargets="BeforeBuild" Condition=" '$(Configuration)' == 'Debug' ">
<!-- Ensure libman is installed -->
<Exec Command="libman --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="libman is required to build and run this project. To continue, please run `dotnet tool install -g Microsoft.Web.LibraryManager.Cli`, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'libman'. This may take several minutes..." />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" Command="libman restore" />
</Target>
</Project>
EDIT:
According to your comment and edited question:
First, The bootstrap package is installed inside the root of wwwroot
.
{
"library": "[email protected]",
"destination": "wwwroot/"
}
However, it is referenced in the JS
folder.
await JSRuntime.InvokeAsync<IJSObjectReference>("import", "/js/bootstrap.min.js");
Second, please remove the line below from _Host.cshtml:
<link rel="stylesheet" href="~/css/bootstrap.css" />
I suggest that you try to refer to the _Host.cshtml
file instead of referring to the OnAfterRenderAsync
method, such as below:
<link rel="stylesheet" href="twitter-bootstrap/css/bootstrap.min.css" />
You can do the same for other libraries, such as Popper
.
Originally, when using LibMan to install Popper, LibMan wanted to put Popper here
Please try this too. It means the default installation path (/lib
) in the libman
folder.
I think that all the differences between the code of my project that is running now and the code of your project were these things.
CodePudding user response:
First, I don't know why you put your js files in App.razor
, I think it is better ot add them in your MainLayout.razor
or _Host.cshtml
:
<script src="~/lib/jquery/jquery.min.js"></script>
Second, I don't think that you need to include Popper because Bootstrap has already this library in bootstrap.bundle.js
, see this link. You can add this file like this:
Solution Explorer -> right click on Project -> Add -> Client-Side Library -> twitter-bootstrap -> choose specific files -> js -> bootstrap.bundle.min.js.
Please note that the files will be added in lib
folder, if you want to change the location, then you need to change your libman.json
and I don't think that necessary to change location, just keep them in lib
folder.
Then, your script in MainLayout.razor
or _Host.cshtml
will be:
<script src="~/lib/jquery/jquery.min.js"></script>
<script src="~/lib/twitter-bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="~/js/BootstrapJavaScript.js"></script>