In this blog post, we are going to make a minor enhancement to the Blazor carousel component in the BlazorStrap library. Modern development makes use of open source code and components all the time. Of course, as described in the backstory below, they often do not do exactly what we want them to do or have bugs/issues that need to be addressed. In these cases, because they are open source, we have an opportunity to fix or enhance the code and contribute our changes back to the public repository. If you are short on time (or attention span), feel free to skip the backstory section below and dive right into the problem section that follows it. Also, for more general instructions on how to make open source contributions, be sure to check out GitHub’s “first contributions” article instructions found here.
Microsoft has a long and distinguished history of releasing software that is, well, let’s just say “not fully baked” in version 1. In the famous words of SNL’s Dr. Wayne Wenowdis, “We know dis…!”. There is little value in going down the rabbit hole of why this happens. Instead, let’s simply acknowledge Microsoft is doing some amazing things, pushing boundaries with new technologies, and effectively uses preview builds and release candidates. In other words, the model is to release sooner and draw live feedback from developers in real time to drive the next iterations. Combine this with adoption of the open-source model and can developers still complain? Yes…and no!
The problem comes with real-world development when all the components programmers need to provide customers with the user experience they have come to expect are not provided out-of-the-box. Developers are left with a few options here:
- Purchase 3rd party controls like DevExpress, Telerik, and others.
- Find and use free, open source, components.
- Roll your own from scratch.
I’m supportive of the first route of purchasing 3rd party controls as that path frequently saves time and project money. However, today, we are going to go down the second route of using open source components. This will let us highlight one of the inconveniences with using free, open source, solutions (which can also happen with 3rd-party controls BTW). Difficulties can arise when the component does not actually do what you want or expect.
The benefit of a decision to use open source, of course, is that we are free to fork/clone the code and make the changes necessary for it to do what we want. That is the path we will explore in this blog post.
The date was 5/19/2021 and, up to this point, I had been using MudBlazor components. Unfortunately, they did not have a carousel component available, but the BlazorStrap component library did have a carousel component available. Long story short, and against my better judgement, I found myself experimenting in a branch to get the two libraries to play nice together. The BlazorStrap carousel component met the requirements because it allowed me to include child content, which was necessary for getting the exact look and feel needed.
As an aside, I mention the exact date above because, as luck would have it, the very next day MudBlazor added a carousel component! By then, of course, I was well down the path with the BlazorStrap library and decided to stay the course with it.
The only problem was that my desired display for each item was somewhat complex. I wanted to display text both above and below some images. I could get a caption to display below an image, but I could not control anything above it. I tried not supplying an image to the component and only using custom child content. That resulted in a missing image icon on the web page. I tried using a 1×1 transparent gif image, which helped, but caused conflicting formatting issues with my child content. A sample result looked like the image here, with my 1×1 image getting stretched to fill space above the desired custom content.
In the end, it was clear that I needed a way to tell BlazorStrap’s carousel component not to render an image by default and that I wanted full control over the item template.
The goals are:
- Prepare a local repo of the BlazorStrap components so necessary changes can be made.
- Enhance the carousel component such that BlazorStrap lets me have full control over the display of each item.
- Make a pull request to contribute my enhancement back to BlazorStrap’s origin repository.
Special contributing guidelines
Before embarking on making an open source contribution, it is wise to check for any special instructions the maintainers of the repository may have published. Generally, you want to look for a markdown file in the root of the source code that is named something like “Contributing.md”.
When you go to make your pull request later, GitHub will remind you to review contributing guidelines, if this is your first commit to the repository.
Many developers are familiar with cloning a repository, but standard procedure when you want to make contributions to an open source repo is to fork it instead.
Fork the repo
Forking a repo in GitHub is as simple as navigating to the project’s home page, https://github.com/chanan/BlazorStrap in this case, and clicking the Fork button in the upper-right.
Forking a repo involves essentially making a copy of it in your own project space. Because you are working with a copy, it is possible to experiment and change things without affecting the original project. A forked repository differs from a clone in that a connection exists between your fork and the original repository itself. Think of a fork as a bridge between the original repository and your personal copy. This article provides more information on the difference between forking and cloning a repository.
Once we have forked the original repository, the next step is to clone our forked version.
Clone the forked repo
By cloning our forked version of the repository, we are able to contribute back to the original project using Pull Requests.
Once you have cloned your forked version of the repository, it might be interesting to inspect the config file located in the .git directory at the root of your clone. Try opening it up in your favorite text editor.
Notice how the contents of the origin setting from my config file in the .git directory is not the BlazorStrap repo on GitHub, but rather one I forked.
As we prepare to make changes, the next thing we’ll want to do is make a branch. This is necessary because you will not likely have contributor access to the main/master branch of open source repositories.
Create a branch
Although, technically you can make changes and then commit those changes to a branch later. I simply prefer to create the branch up front. In any case, now that we have a new branch created, it is time to start making changes.
Make necessary changes and commit those changes
In this particular case, I am able to locate the cause of my troubles in a BSCarouselItem.razor file. I can see that no matter what it is going to add either an <img> tag or a <BSSvg> tag in front of the @ChildContent.
To fix this, I simply add a check to see if the Src parameter has a value or not via String.IsNullOrWhitespace(). In other words, if no value was supplied for a source image, I want the component to only display the child content and not add what will ultimately be either a missing image, or a transparent pixel.
With the fix made, it is time to test the change. This can be done by creating a NuGet package and updating your own project to use it.
Create a NuGet package
In order to install updates to an NuGet package, it may be necessary for you to bump the version number of the project. Keep in mind this is only for your own testing. The origin may use an automated pipeline or have its own opinion on what version number should be used.
Even though I bump the version number locally, I will not commit this particular change to the repo after testing passes.
Test your changes
Update your local project to use the version of the NuGet package that you just generated. Note that there are alternate methods for testing such as making a project reference to the source project instead. That approach can be particularly helpful for more advanced debugging scenarios.
After updating your local test project to use the NuGet package you just generated, or making a project reference instead, give it a spin and see if it works as desired.
Our simple change works! Now, let’s tie up some loose ends here.
- Do you need to create any unit tests for your changes?
- Do all the existing unit tests still pass?
- Be sure to also update documentation that relates to your change.
With everything in order, it is now time to commit our changes locally and push them to our forked version of the repository.
Push changes to GitHub
The procedure for pushing changes to our forked repo is straightforward and can be done from within Visual Studio.
We’re almost done, with the change made in our personal copy of the repo, it is time to contribute them back to the origin repository (i.e. github.com/chanan/BlazorStrap)
Submit your changes for review
Upon navigating to your forked repository on GitHub, a Compare & pull request button will appear in the upper-right. Click on that Compare & pull request button.
Now we just have to fill out some information to give the maintainers of the repository an idea of what this change does and whether it addresses one of the known issues.
Submit the pull request
After filling out the description of your changes, simply click the Create pull request button located in the lower-right.
You will receive an email notification email once the reviewer merges your changes into the main/master branch.
You have just walked through the typical fork | clone | edit | pull request process used to contribute to open source!