6 Replies Latest reply on Aug 20, 2016 6:33 PM by Aaron Anderson

    Errai 4 Widget onLoad alternative

    Aaron Anderson Newbie

      With the GWT steering committee's announcement that widgets will be removed or deprecated in GWT 3.0 I have begun investigating how I can refactor my application to accommodate for this in GWT 2.8 and Errai 4.0. I examined the errai-security-demo which has been updated to not extend the Composite widget class and I was able to successfully apply this change to a test page and template in my Errai 4.0 application as well.

       

      The challenge I am having is that in my application I extensively override the onLoad widget method in my Errai template classes to active javascript behavior in GWT rendered DOM elements. For example in my test application I am using the Google Material Design Lite framework and I need to call componentHandler.upgradeDom()  when the template is loaded to apply the MDL JavaScript functionality to the rendered elements.  If my Errai templates no longer extend composite I am not sure how to perform the initialization. So far I couldn't find a way to obtain a Document element reference to the root template element to try to add an event listener to that. Also I have never had any luck trying to use any of the lifecycle annotations (@PostCreate, @PageShowing, etc) to initialize javascript behavior and only overriding the onLoad method worked.

       

      What is the suggested way to prime native JavaScript libraries in Errai 4.0 without using widget functionality?

       

      Also since I need to perform this initialization for every single page is there a way I could use a global event listener to perform this task instead of having to add it to each page template?

        • 1. Re: Errai 4 Widget onLoad alternative
          Max Barkley Expert

          Hi Aaron,

           

          Assuming you don't want to execute your JavaScript before your component is attached to the DOM, I'd recommend using @EventHandler to declare a handler for AttachEvents (see here). If you can execute your script before the component is attached to the DOM, a @PostConstruct method might be the best place.

          So far I couldn't find a way to obtain a Document element reference to the root template element to try to add an event listener to that.

          In Errai 4 the root element of a template can be accessed as a data field like any other element in the template. Thus the simplest way to manipulate that element is to give your root element an id/class/data-field in your html file so that you can have a @DataField for it in your Java file.

          What is the suggested way to prime native JavaScript libraries in Errai 4.0 without using widget functionality?

          The suggestions above will work, but we are still researching how Errai UI should interact with native JS libraries. If you have suggestions for how you might like this to work (maybe there is a declarative feature that could handle this), now is a great time to have those discussions.

          Also since I need to perform this initialization for every single page is there a way I could use a global event listener to perform this task instead of having to add it to each page template?

          There's no feature in Errai particularly for this kind of task, but you could have all your templates extend a common base class that declares the @PostConstruct or @EventHandler to run your JS.

           

          Cheers.

          • 2. Re: Errai 4 Widget onLoad alternative
            Hristo Stoyanov Master

            Aaron and Max,

            Thanks for sharing.

             

            Aaron,

            Have you considered the "Gwt Material Design" project instead of google's simplified "Material Design Light"?

             

            Seems a lot more mature, is based on MaterializeCSS. I have not tried to use it with Errai 4. That is in my plans...

             

            I have used before Semantic UI with Errai 3, had to deal with a lot of JSNI to interop with jQuery. Hopefully I can simplify all this with GWT 2.8 JSInterop now. (But the developer of SUI is missing-in-action lately, could be risky to base a new project on Semantic UI)

             

            Cheers

            • 3. Re: Errai 4 Widget onLoad alternative
              Aaron Anderson Newbie

              Thanks for the tip on the GWT Material Design project. It looks very mature and feature complete. I am currently using a commercial Bootstrap theme for my application and I recently learned the author will no longer be maintaining it. Now that I am at the point of needing to upgrade my project I thought I would forge ahead and update my project to be compliant with the future direction of GWT 3.0: no widgets or JSNI and more support for native frameworks such as web components and Material Design Lite.

              • 4. Re: Errai 4 Widget onLoad alternative
                Aaron Anderson Newbie

                I am still struggling to execute JavaScript after Errai template HTML is add to the DOM with Errai 4.0. I have tried the following:

                 

                1)

                @EventHandler

                  public void onAttach(AttachEvent levent) {

                  logger.info("onAttached called");

                  }

                 

                This generates a compiliation error: org.jboss.errai.codegen.exception.GenerationException: @EventHandler method [onAttach] in class [acme.client.local.Errai] must have exactly one parameter of a type extending either [com.google.gwt.event.dom.client.DomEvent] or [com.google.gwt.dom.client.NativeEvent].

                 

                2)

                 

                  @Inject

                  @Named("div")

                  @DataField

                  private HTMLElement top;

                 

                @PostConstruct

                  public void init() {

                  top.addEventListener(BrowserEvents.LOAD, e-> Window.alert("Loaded"), false);

                }

                 

                The event is not triggered because the load event is not generate on DIVs.

                 

                3)

                @EventHandler

                  public void onLoad(LoadEvent levent) {

                   Window.alert("Loaded");

                  }

                 

                Complies but is not invoked either.

                 

                Since gwt-user will eventually be deprecated is there an alternative to AttachEvent that can be utilized?

                • 5. Re: Errai 4 Widget onLoad alternative
                  Max Barkley Expert

                  Hi Aaron,

                   

                  Currently this can't be done declaratively. Here is code that will work in your @PostConstruct to register a listener for a DOM mutation event:

                      root.addEventListener("DOMNodeInsertedIntoDocument", e -> {
                        if (root.getId().equals(((HTMLElement) e.getTarget()).getId())) {
                          Window.alert("attached " + e.getTarget());
                        }
                      }, false);
                  

                  In the above, root is of type Div and the element that is the root of your template (which an be accessed with @DataField).

                   

                  That being said, mutation events have been deprecated. You might consider finding/writing a JS interop wrapper for new Mutation Observer API, and trying that out.

                  • 6. Re: Errai 4 Widget onLoad alternative
                    Aaron Anderson Newbie

                    I discovered a useful side effect to execute the script element in my template. When Errai loads a template it creates a new DOM element by passing in the string text of the template. This does not trigger the script execution as mentioned above. However if I set an ID on the script element:

                     

                    <script id="app-header-init">

                     

                    and then in my template I inject the script:

                     

                    @Inject

                    @DataField("app-header-init")

                    private ScriptElement script;

                     

                    the script is executed. This is because Errai takes the text of the script element and creates a new DOM element using it and then replaces the existing script text in the template. The act of creating a new script element triggers the script body to be executed.