javascriptmavengwtbootstrap-5

How to include latest bootstrap 5 javascript library into a modern GWT application


I know there are some outdate and deprecated / no more supported projects like GWT-Bootstrap (https://github.com/gwtbootstrap/gwt-bootstrap) and gwtbootstrap3 (https://github.com/gwtbootstrap3/gwtbootstrap3) who integrate the Bootstrap library into GWT projects, however I know it's possible to use standard javascript Bootstrap library (https://getbootstrap.com/) into a modern GWT App (for modern I mean 'at the ages of 2025' using for example the Thomas Broyer Maven artifact). I know for example it should be possible to include it as a Maven dependency this way:

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>5.3.7</version>
</dependency>

The question is: is there a guide, a tutorial, some documentation or an article online or could someone explain how to use it with a demonstration?


Solution

  • You can use the modern standard way to integrate Bootstrap as a third-party JS-library into your GWT application.

    1. Maven dependency:

    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>bootstrap</artifactId>
        <version>5.3.7</version>
    </dependency>
    

    2. Including Bootstrap CSS and JS in the host HTML:

    Use WebJar locator or manually reference.

    <link rel="stylesheet" href="webjars/bootstrap/5.3.7/css/bootstrap.min.css" />
    <script src="webjars/bootstrap/5.3.7/js/bootstrap.bundle.min.js"></script>
    

    3. Using Bootstrap styles in GWT widgets:

    For Bootstrap's JS-driven components (modals, dropdowns, tooltips), you’ll need to initialize them manually via JSNI or JsInterop calls, as GWT widgets do not automatically handle Bootstrap's data attributes like data-bs-toggle.

    @JsMethod(namespace = "bootstrap")
    public static native void Modal(Element element);
    
    public void initModal(Element modalElement) {
        Modal(modalElement);
    }
    

    4. Using JsInterop for Bootstrap JS API:

    @JsType(isNative = true, namespace = "bootstrap", name = "Modal")
    public class Modal {
        public Modal(Element element) {}
        public void show() {}
        public void hide() {}
    }
    
    Element modalEl = Document.get().getElementById("myModal");
    Modal modal = new Modal(modalEl);
    modal.show();
    

    Official documentation

    5. Handling Bootstrap's data attributes:

    myWidget.getElement().setAttribute("data-bs-toggle", "dropdown");
    

    Or create custom widgets that expose setters for these attributes.

    6. Using the component in UiBinder:

    <g:HTMLPanel>
            <g:Button ui:field="showModalButton" styleName="btn btn-primary">
                Launch demo modal
            </g:Button>
    
            <div class="modal fade" ui:field="myModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
                <div class="modal-dialog">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
                            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                        </div>
                        <div class="modal-body">
                            This is a Bootstrap 5 modal controlled by GWT and JsInterop!
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                            <button type="button" class="btn btn-primary">Save changes</button>
                        </div>
                    </div>
                </div>
            </div>
        </g:HTMLPanel>
    </ui:UiBinder>
    

    7. Using in Java View:

    import elemental2.dom.HTMLDivElement;
    import jsinterop.base.Js;
    
    public class MyView extends Composite {
        interface MyViewUiBinder extends UiBinder<Widget, MyView> {}
        private static MyViewUiBinder uiBinder = GWT.create(MyViewUiBinder.class);
    
        @UiField
        Button showModalButton;
    
        @UiField
        HTMLDivElement myModal;
    
        private BootstrapModal modal;
    
        public MyView() {
            initWidget(uiBinder.createAndBindUi(this));
        }
    
        @Override
        protected void onAttach() {
            super.onAttach();
            ModalOptions options = ModalOptions.create(true, "static", true);
            this.modal = new BootstrapModal(myModal, options);
    
            myModal.addEventListener("shown.bs.modal", evt -> {
                GWT.log("Modal was shown");
            });
            
            myModal.addEventListener("hidden.bs.modal", evt -> {
                GWT.log("Modal was hidden");
            });
        }
        
        @Override
        protected void onDetach() {
            super.onDetach();
            if (this.modal != null) {
                this.modal.dispose();
            }
        }
    
        @UiHandler("showModalButton")
        void onShowModalClick(com.google.gwt.event.dom.client.ClickEvent e) {
            if (this.modal != null) {
                this.modal.show();
            }
        }
    }