Conversation
|
I know we ship with bootstrap as an example, but end grails applications technically don't have to use it. Do we default style any of other tags this way? |
All of these are framework-agnostic class names - none reference Bootstrap ( The classes are overridable via attributes ( |
@jdaugherty if you look at all the locations where this tag is being used (scaffold and default layouts), it is replacing bootstrap code. <g:if test="\${flash.message}">
<div class="alert alert-primary" role="alert"><i class="bi-info-circle"></i> \${flash.message}</div>
</g:if>@jamesfredley all those tags actually reference proprietary grails classes that end users shouldn't be using. My plan was eventually to swap those defaults out to bootstrap classes considering all those hardcoded grails classes are no longer used and the css has since been deleted. motivation behind this PRFlash messages should fallback to being displayed in the layout. That way utilizing flash.message in a controller will always result in the flash message being displayed. There is no requirement for utilizing this tag lib, but, like the other g: tags, the classes are overridable. |
|
Just thinking out loud: Could the CSS class defaults be set (and overridden) in configuration? Then we could default to the Bootstrap theme classes in |
|
Another possibility is to push a custom tag lib with the Scaffolding plugin. I don't think we should be putting css framework specific classes in grails-gsp. I'm ok to do that in scaffolding since there's precedence there. |
|
@codeconsole My suggestion is to make generic output, and follow the way the fields plugin works. Have a structure like: And if they are not defined revert back to sensible |
@matrei Of course the other option is don't use the tag at all. |
@jdaugherty isn't there already css framework specific classes in virtually every other grails tag? This really has nothing to do with scaffolding. It targets |
Doing some analysis with AI: it thinks that bootstrap classes aren't hard coded today - only the basic grails classes: Grails TagLib CSS Classes AuditAn inventory of all hardcoded CSS classes in shipped Grails tag libraries. UrlMappingTagLib — Pagination & SortingFile:
|
| CSS Class | Overridable? | Notes |
|---|---|---|
prevLink |
No | Applied to the previous page link |
nextLink |
No | Applied to the next page link |
step |
No | Applied to each page number link |
step gap |
No | Hardcoded <span class="step gap">..</span> for ellipsis gaps |
currentStep |
Yes (activeClass attr) |
Default class for the active/current page |
<g:sortableColumn>
| CSS Class | Overridable? | Notes |
|---|---|---|
sortable |
No | Always added to the column |
sorted |
No | Added when column is the active sort column |
asc / desc |
No | Sort direction appended as a class alongside sorted |
FormFieldsTagLib — Field Wrappers
File: grails-fields/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy
<f:field>
| CSS Class | Overridable? | Notes |
|---|---|---|
fieldcontain |
Yes (class attr) |
Default wrapper div class |
error |
Yes (invalidClass attr) |
Added when the field has validation errors |
required |
Yes (requiredClass attr) |
Added when the field is required |
required-indicator |
No | Hardcoded on <span> containing * |
RenderTagLib — Error/Exception Display
File: grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy
<g:renderException>
| CSS Class | Overridable? | Notes |
|---|---|---|
error-details |
Yes (detailsClass attr) |
Default class on the <dl> element |
stack |
Yes (stackClass attr) |
Default class on the <pre> element for stack traces |
Summary
| TagLib | Tag | Total Classes | Overridable | Not Overridable |
|---|---|---|---|---|
| UrlMappingTagLib | paginate |
5 | 1 | 4 |
| UrlMappingTagLib | sortableColumn |
3 | 0 | 3 |
| FormFieldsTagLib | field |
4 | 3 | 1 |
| RenderTagLib | renderException |
2 | 2 | 0 |
| Total | 14 | 6 | 8 |
Assessment
- No CSS framework dependency. The hardcoded class names (
sortable,step,error, etc.) are semantic/functional names. They do not correspond to Bootstrap, Tailwind, or any other CSS framework. - 8 of 14 classes are not overridable. The
paginateandsortableColumntags inUrlMappingTagLibare the primary concern, with 7 non-overridable classes between them. Users must target these specific class names in their stylesheets. - Most FormFieldsTagLib and RenderTagLib defaults can be replaced via tag attributes.
CustomTagLib.groovyingrails-test-examples/contains Bootstrap-like patterns (panel,alert,badge,progress-bar) but is a test fixture, not part of the shipped framework.
@jdaugherty what is the difference between a bootstrap css class or a custom grails class that requires importing an additional css rule? At the end of the day, it is just a css class. If you don't have bootstrap, you could just write your own rule for it or write no rule in which the css classes would have no effect. I would much rather see well thought out bootstrap classes than css classes that don't even exist anymore in the codebase. My original plan for 8 was to swap all the deprecated default grails class names with bootstrap ones. |
|
@codeconsole This is for 7.1 though. I'd agree with you if we were on bootstrap exclusively. Although, I debate if we should do that with css frameworks like tailwind. For 7.1, I think we should move it to it's own tag lib or make it configurable. |
| * @attr role ARIA role for alert divs (default: 'alert') | ||
| * @attr dismissible Whether to show a close button (default: true) | ||
| */ | ||
| Closure flashMessages = { attrs -> |
There was a problem hiding this comment.
We discussed this in the weekly and we need to release 7.1 soon. For a quick resolution here and to make it in 7.1, we should either make this configurable at the app level or move it to the scaffolding project with a custom tag lib. Otherwise, we can revisit this in 8.0.
|
The comment proposes two quick fixes for the hardcoded Bootstrap 5 styling in the new |
Flash Messages Tag (
g:flashMessages)Introduces a new
<g:flashMessages />tag that rendersflash.message,flash.error, andflash.warningas Bootstrap5 dismissible alerts with appropriate styling (success, danger, and warning respectively).
The tag automatically prevents duplicate rendering -- if called in both a page and its layout, only the first invocation produces
output. All flash content is HTML-encoded to prevent XSS.
The default layout (
main.gsp) and all scaffolding templates now use this tag. If your application has custom views that renderflash messages manually, you can replace the boilerplate:
This tag has been introduced to all default layouts so that every page has automatic access to displaying flash.* messages. Multiple
<g:flashMessages />are supported, but the first one rendered is prioritized. Because of this, if a view (e.g.: scaffold view) has a<g:flashMessages />, that flash.message location is prioritized over the layout location.Purpose
Renders
flash.message,flash.error, andflash.warningas dismissible Bootstrap alert divs with appropriate styling.Automatically prevents duplicate rendering when used in both pages and layouts.
Examples
Basic usage in a view:
In a layout (safe to use alongside page-level usage -- the tag skips rendering if already called):
Non-dismissible alerts:
Custom ARIA role:
Custom styling for success messages:
Setting flash messages in a controller:
Description
The
flashMessagestag renders any combination offlash.message,flash.error, andflash.warningas Bootstrap 5 alert divs.Each flash key maps to a different alert style:
flash.messagealert alert-success alert-dismissible fade showbi bi-check-circle me-2flash.erroralert alert-danger alert-dismissible fade showbi bi-exclamation-triangle me-2flash.warningalert alert-warning alert-dismissible fade showbi bi-exclamation-circle me-2The tag automatically sets a
_flashRenderedrequest attribute after rendering. On subsequent calls within the same request, thetag detects this attribute and outputs nothing. This allows both pages and layouts to include
<g:flashMessages />withoutproducing duplicate alerts -- whichever renders first wins.
All flash message content is HTML-encoded to prevent XSS.
Attributes
messageClass(optional) - CSS class forflash.messagealerts. Default:alert alert-success alert-dismissible fade showmessageIcon(optional) - Icon class forflash.messagealerts. Default:bi bi-check-circle me-2errorClass(optional) - CSS class forflash.erroralerts. Default:alert alert-danger alert-dismissible fade showerrorIcon(optional) - Icon class forflash.erroralerts. Default:bi bi-exclamation-triangle me-2warningClass(optional) - CSS class forflash.warningalerts. Default:alert alert-warning alert-dismissible fade showwarningIcon(optional) - Icon class forflash.warningalerts. Default:bi bi-exclamation-circle me-2role(optional) - ARIA role for alert divs. Default:alertdismissible(optional) - Whether to show a close button. Default:true