Extend TMS WEB Core with JS Libraries with Andrew: Bootstrap
So What is Bootstrap?
Bootstrap is essentially an enormous collection of JS code and CSS styles that allow you to quickly design modern, mobile-first and responsive websites. Beyond just marketing hype though, it does this by providing a robust framework of CSS classes that help organize a typical website into a structure that works well in many different browser environments. Indeed, if you were starting from nothing and didn’t have an IDE or other development tools, it is possible to do quite a bit of layout and design work just with Bootstrap by itself. Fortunately we don’t have to work at that level. Instead, we can simply use these Bootstrap classes in all kinds of ways with standard TMS WEB Core components.
Adding Bootstrap to Your Project
If you’ve got an existing TMS WEB Core project that you want to add Bootstrap to, it is just a few minutes to get it installed. As we covered in the introduction for this blog series, there are a few considerations here. But the easiest way is to just use the “Manage JavaScript Libraries” feature of the IDE:
Using this option, or creating a new TMS WEB Bootstrap Application will setup the necessary links in the Project.html file and will include a copy of the necessary Bootstrap library code in your project directly. No need for a CDN or external links. If you’d prefer to use a CDN instead, you can add the following links to your Project.html, as per the Bootstrap website:
https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
I’ve also included the Bootstrap Icons in the above links. More on that a bit later. Popper is another JS library that is used to display popup dialogs and other things. The Bootstrap folks have conveniently included it in their “bundle” distribution but you could choose a smaller package if you really didn’t need any of that functionality. These links also reference Bootstrap 5 (or later) which no longer has a dependency on jQuery. So it doesn’t much matter where Bootstrap appears in the order, if you have multiple JS libraries in your project. If you’re using an older version of Bootstrap (v4 or earlier) then be sure to check that jQuery is loaded first.
So. Many. Classes.
The Bootstrap website is an excellent source of documentation for all the many features they offer, complete with many examples. One of the better sites for documentation of all the JS libraries we’re likely to cover. However it can be a bit overwhelming particularly if this is new to you and you’re not sure where to start. Because Bootstrap covers so many different areas, it is sometimes better to think of it as a set of CSS classes that allow you to tweak your web page in different ways. If you’re looking at your page and thinking “I wish this could be moved over a bit” or “I wish this element would resize to fill this area” then you’re in the ballpark of how to get started with Bootstrap.
Now, to be fair, Bootstrap can do a LOT of different things. What we’re going to start with though are some simple examples that help illustrate where we can plug in Bootstrap classes and why we might want to do that versus some of the alternatives. Let’s consider the simplest of TMS WEB Core components, a TWebEdit control. If you drop one of these on an empty form and then run the project, you’ll get a perfectly functional edit field on a web page. But what if you decided it would be better if the text entered into the edit field was centered? Back in the IDE, find the ElementClassName property of the TWebEdit control. Simply add the value text-center to this property. When you run the project now, entering text into the edit field results in it being centered within the field. That’s Bootstrap at its most basic.
Sample Project
In this sample project, we’re treating Bootstrap classes as a tool for adding extra capabilities or extra properties to individual components. And this is certainly one of the simplest and most helpful use-cases for Bootstrap. And it works across pretty much any type of component (or HTML element). Try swapping out a TWebEdit for a TWebButton for example, and it works pretty well the same way. All of the standard TMS WEB Core components have at least one property, typically ElementClassName, where you can add Bootstrap classes. Many have additional properties, particularly when the component ends up being rendered as multiple (or nested) HTML elements. For example, the TWebLabel component has a separate ElementLabelClassName property so that you can style the label HTML element separately from the encompassing TWebLabel element. And in the case of TWebLabel you can also change the HTMLType property if you want generate something other than a label HTML element.
NOTE: FNC components are a great addition to any TMS WEB Core project. However, ElementClassName and related properties are conspicuously absent from FNC components. If you find this to be limiting in some way, the current best approach is to place a TWebHTMLDiv component on your form. And then place the FNC component within it, using the TWebHTMLDiv as a wrapper for the FNC component, and giving you access to ElementClassName and related properties.
The sample project includes the Bootstrap Icons in its Project.html file. This means that these icons can be added to your elements by simply adding in specially formatted strings, such as as in the screenshot above. There is a pretty good selection of 1,600 Bootstrap Icons. Where this works and where it doesn’t isn’t always obvious. In the case of TWebLabel component, you should use the HTML property instead of the Caption property to have these icons displayed properly. In the case of TWebButton, the Caption property works as-is. More often than not, wherever you can place visible text you can also embed icons in this way. While Bootstrap Icons are pretty great, the next JS library we’re going to cover is FontAwesome which is considerably larger and far more flexible not only in terms of the icons themselves but also in terms of what you can do with them. Stay tuned!
Sweating the Details
Using Bootstrap in this way provides you with the means to endlessly tweak the look and feel of your web application. It is entirely possible to have pixel-perfect layouts that work cross-browser and that are responsive. Meaning that you can view the web application on any device and it will automatically adjust to fit whatever dimensions it finds itself in. The Sample Project, for example, should automatically show or hide scrollbars as needed to fit the TWebMemo at the bottom of the page. And the layout with the borders and the rounded corners and the rest of it should also adjust automatically as you resize your browser window, for example.
For a simple layout like what is found in the Sample Project, this isn’t particularly interesting. But it is a good start in terms of understanding how and when HTML elements resize themselves. And how various Bootstrap classes can be strategically placed all over (some might say littered…) to ensure that elements have the appropriate padding and margins and are positioned relative to one another in a way that allows this all to work seemingly naturally. And really this is just the starting point. But even with just this extra bit of functionality enabled with the use of Bootstrap, it is already quite feasible to make a web application that is nearly pixel-perfect in terms of layout and overall appearance.
How you architect the styling and layout of your app will suddenly become important, however. For example, if your web application uses a template or CSS separately from your TMS WEB Core application, then adding Bootstrap classes here and there and everywhere may be both unwelcome and ineffective. Likewise if you’ve gone through a lot of effort to craft CSS styles to do a lot of the same kind of work. There may be a desire to cleanly separate out the layout and styling into different areas of responsibility. For my projects, I tend to put a lot of emphasis on having CSS to do the bulk of the heavy lifting for the styling aspects. But I do sprinkle Bootstrap classes in places to help reduce the need for adding CSS tweaks everywhere. I find combining the two and using the IDE for the bulk of the layout of the components tends to work best for me. The Sample Project shows how this all works together. But I fully understand that this may not be the case for everyone. One of the clear goals of the TMS WEB Core design was to make it not only possible but easy to architect web applications with these kinds of considerations in mind.
Beyond the Basics
Tweaking the layout of individual components is pretty straightforward and easy to do. And fun! Kind of empowering to be able to look at a page and be able to adjust pretty much everything on it to your liking. Moving beyond individual components, however, there are a great many more things that Bootstrap can do.
One of the more substantial areas where Bootstrap comes into its own relates to its handling of layouts and the use of flexbox and responsive breakpoints and the rest of it. If you came here specifically for details on that, all I can do is refer you to any of hundreds of online tutorials that go into every detail about how it all works. But it does indeed work very well. To use this sort of thing in a TMS WEB Core application, one approach might be to nest TWebHTMLDivs and apply the appropriate container, column or row classes as needed. And there are several components included with TMS WEB Core to help do this kind of thing as well, such as TWebGridPanel.
A Bootstrap feature I’ve grown rather fond of is their Button Groups. I find I prefer the styling of these as an alternative way to control pages of a TWebPageControl, rather than the tabs that come with that component. And they’re pretty easy to setup.
- Add a TWebPanel to your form. Set ElementBodyClassName to include btn-group and d-flex
- Add as many buttons as you like to this TWebPanel. Set ElementClassName to include btn btn-primary or other btn classes
- Additional Bootstrap classes can help with various layout possibilities
For example, Bootstrap will automatically round the first and last buttons, provide highlighting for the current active button, and automatically size the buttons based on their contents to fill the space available:
And Button Groups are just one of more than 20 additional components offered by Bootstrap. Others include things like Accordion Menus, Navigation Bars, Progress Bars, Cards, Carousels, and so on, which can be integrated into your TMS WEB Core project in much the same way.
Bootstrap versus CSS and !important
There’s a bit of a battle between Bootstrap and CSS rules in a project. Sometimes adding a Bootstrap class has no impact because there is a bit of CSS that has taken precedence. Or some aspect of the layout prevents some other aspect of the layout from behaving in the desired manner. And it can work both ways. Sometimes a Bootstrap class inadvertently gets slipped in that adds an extra margin or an unexpected font size change despite the best laid CSS plans. Tracking these down can sometimes be tricky, but fortunately the standard browser developer tools usually make quick work of identifying who won the battle for whatever property you’re concerned with. Then it is a matter of making the adjustments to override the undesirable outcome.
When CSS loses to Bootstrap, this far too frequently means adding a class with an extra !important flag tagged onto the end of it to ensure that your CSS overrides the Bootstrap values. It would also be good to check that your CSS file is loaded after Bootstrap. It is then possible to use CSS to redefine some of Bootstrap’s defaults simply by re-declaring them in your own CSS rules. Occasionally an extra div is added as a prefix to ensure it gets bumped up in the precedence order, ahead of the Bootstrap CSS definitions. Bootstrap itself can also be directly customized in various ways if you find you simply don’t like how some aspect of it works.
When Bootstrap loses to CSS, with a little luck it is just a matter of adjusting the CSS to be more specific so that it gets out of the way. This of course is somewhat the opposite of what you normally want to do with CSS (the less specific the better, generally speaking). Bootstrap has plenty of its own !important flags however. So the struggle can be quite real!
That’s a Wrap!
Andrew Simard.