Awesome
Demo project for integrating Blazor components into an existing Angular app.
Motivation
Although Blazor is a great choice for creating web frontends, abolishing an existing Angular app and starting from scratch is often no option. This project demonstrates, how Blazor components can be integrated in an existing Angular project, making it possible to migrate step by step.
Live demo
Visit this demo deployed to github pages by our github CI/CD script.
How to compile and run
In the src-blazor
folder, there is a Blazor solution with two projects. dotnet build
the AngularAdapterBuild
project first, then dotnet publish
the BlazorComponents
project. This will
create the Angular-to-Blazor bindings in the Angular project and copy the Blazor runtime into
the bin-blazor
directory.
In the root folder, there is a usual Angular project. Call npm install
and npm start
to run it.
If you want to test the Blazor components on its own, in the BlazorComponents
project set the Settings.isTestEnvironment
field to true
and run the project in Visual Studio 2022. This will
open a browser window, showing the components in a test environment without Angular.
Troubleshooting
As of December 2021, creating Blazor components for JS projects is still in a very early stage, so expect API changes and problems. Some problems we encountered:
-
Over and over again, we experienced problems when building the C# solution. In this case, close Visual Studio and reopen it. Rebuild the
AngularAdapterBuild
project first, then rebuild and publish theBlazorComponents
project. -
In the Firefox browser, from time to time we experienced the problem of the Angular app throwing the error
"Response.arrayBuffer: Body has already been consumed."
. When deployed to github pages, the error seems to appear quite often (but not always). We do not know the reason for this problem yet, however it works both in Chrome and Edge browser.
Implementation details
Here are the basic steps how we implemented the demo based on the original Angular project:
- [Commit] We used an existing Angular application. In our case, we cloned the Angular RealWorld example app. We compiled and ran the Angular app to make sure everything was working so far.
- We added a new directory
src-blazor
. Of course this directory could be anywhere and does not have to be a subdirectory of the Angular project. - [Commit] We created a Blazor .NET WebAssembly project in this directory. For the beginning just a runnable app with a simple counter component.
- For the demo, we wanted to replace the Angular component
ArticleCommentComponent
by a Blazor component.- [Commit] The required model classes are
Comment
andProfile
. We ported them to C# records. - [Commit] We created the
ArticleComment
component in Blazor. For the moment, we just implemented the HTML and parameters, not the logic like the Angular service. For correct appearance of the component, we included the external CSS content from the Angular project into the Blazorindex.html
. - [Commit] For trying out the component in a pure Blazor context (multiple instances of the component on one page, routing to a different page), we created a minimal Blazor routing environment with pages.
- [Commit] The required model classes are
- [Commit] For building an Angular component from our Blazor component, we added a class library project
AngularAdapterBuild
to our C# solution. It is very much based on the JavaScript component generation sample from the ASP.NET Core samples with two important fixes: Updating all libraries to latest version, and callingRegisterForJavaScript
method with thejavaScriptInitializer
parameter, see open issue #38044. - [Commit] For loading the Blazor binaries into our Angular app, we created a folder
bin-blazor
into which theBlazorComponents.csproj
buildfile publishes the Blazor runtime (_framework
folder) and theBlazorComponents.styles.css
styles. Inangular.json
, we defined both artifacts as assets to include them in the built Angular app. In thesrc/index.html
of the Angular app, we loaded the CSS file and initialized Blazor. - [Commit] Now we could use the Blazor component in the Angular app. We imported it in a module and used the original Angular component and our new Blazor component side by side for comparison.
- [Commit] We added event handling both in the Blazor test environment and the Blazor app; added an additional event for testing.
- [Commit] Since we had to call a method from an Angular service (a method from the
UserService
in our example), we exposed this method to thewindow
object and called it in our Blazor code. We added ablazor-bridge.service.ts
service to collect all required Angular service methods there. - [Commit] To clean up the Blazor code, we created an
IAppService.cs
service interface for the required Angular service methods with two implementations:TestAppService.cs
for the Blazor test environment,AngularAppService.cs
for the real Angular environment using JS interop calls. - [Commit] We added integration for github CI/CD with deployment to github pages for creating a live demo automatically.
Thank you
This demo project is based on the Angular RealWorld example app by Thinkster. Thank you very much for the useful template.