WFF

wffweb - Java framework to develop web applications

View sample projects on GitHub

Build UI with minimal tags

When building heavy UI, it's important to follow this rule to keep only necessary tags. It reduces the load of a browser, why should the browser take care about unnecessary tags!!

Use minimal tag manipulation methods

If there are continuous invocation of tag manipulation methods then try to convert it to invoking minimal tag manipulation methods. Check out the below examples

Eg 1 :-

List children = div1.getChildren();
        
for (AbstractHtml child : children) {
    div1.removeChild(child);
}

//should be as follows instead of the above
div1.removeAllChildren();

Eg 2 :-

div1.removeAllChildren();
div1.appendChild(div2);

//should be as follows instead of the above
div1.addInnerHtml(div2);

Eg 3 :-

div1.removeAllChildren();
div1.appendChild(div2);
div1.appendChild(div3);
        
//should be as follows instead of the above
div1.addInnerHtmls(div2, div3);
Use BrowserPage#holdPush & BrowserPage#unholdPush wherever possible

Surround with BrowserPage#holdPush and BrowserPage#unholdPush methods for multiple tag manipulation statements. When a tag manipulation method (eg: div.removeAllChildren() ) is executed the framework sends its UI update to the client as a push so if there are multiple statements then there will be multiple push. When all tag manipulation methods are surrounded with BrowserPage#holdPush and BrowserPage#unholdPush then all those UI updates will be sent in a single push so that the end user will not see the UI changes are taking place one by one in a slow network. Also ensure that the BrowserPage#unholdPush() is called inside finally block. See the sample code given below

Eg :-

try {
    browserPage.holdPush();
            
    div1.addAttributes(new Style("background:green"));
    div2.addAttributes(new Id("div2Id"));
    div3.addAttributes(new Name("div3"));
    div1.addInnerHtmls(div2, div3);
} finally {
    //pushes UI updates for the above four methods in a single push
    browserPage.unholdPush();
}

But there are also cases where these methods are not suitable, for example you are adding up to 1000 rows (or more than that) in a table. In such case if you are writing that code between BrowserPage#holdPush and BrowserPage#unholdPush then the end user will have to wait a long time to see the result because the framework sends all changes in a single push and the browser displays it only after receiving all these UI updates. Here, the end user is expecting a lazy loading. In such scenarios it's better to avoid using these BrowserPage#holdPush and BrowserPage#unholdPush methods.

The usage of BrowserPage#holdPush and BrowserPage#unholdPush methods depends upon the requirements.

Do not return anonymous class

When you want to reuse a set of tags, you have to keep a separate template class for it. Eg:-

First let us look at a bad practice :-

public class UserDetails {

    public Div getUserDetailsDiv(final String fullName) {

        Div details = new Div(null) {
            {
                new Span(this) {
                    {
                        new NoTag(this, "Name : ");
                        new NoTag(this, fullName);
                    }
                };
            }
        };

        return details;
    }

}

public static void main(String[] args) {
    UserDetails userDetails = new UserDetails();
    System.out.println(
                userDetails.getUserDetailsDiv("Hitomi").toHtmlString());
}

Use the below code instead which does the similar job

public class UserDetailsTemplate extends Div {

    public UserDetailsTemplate(String fullName) {
        super(null);
        develop(fullName);
    }

    private void develop(final String fullName) {

        new Span(this) {
            {
                new NoTag(this, "Name : ");
                new NoTag(this, fullName);
            }
        };

    }

}

public static void main(String[] args) {
    UserDetailsTemplate userDetails = new UserDetailsTemplate("Hitomi");
    System.out.println(userDetails.toHtmlString());
}

But if you really want a method to return a div, then you have to change the coding style like this

public class UserDetails {

    public Div getUserDetailsDiv(final String fullName) {

        Div details = new Div(null);

        Span span = new Span(details);

        new NoTag(span, "Name : ");
        new NoTag(span, fullName);

        return details;
    }

}

public static void main(String[] args) {
    UserDetails userDetails = new UserDetails();
    System.out.println(
                userDetails.getUserDetailsDiv("Hitomi").toHtmlString());
}

Next >>