How to add button in HeaderSpan of SmartGWT

2019-03-04 02:34发布

问题:

I want to add a button to the HeaderSpan of ListGrid in SmartGWT. I tried using the 'HeaderSpan.setAttribute((String property, Object value)) method but it did not work. Below is the example I tried with:-

ListGrid countryGrid = new ListGrid();
HeaderSpan ident = new HeaderSpan("Identification", new String[]{"countryCode", "countryName"});
ident.setAttribute("control", new Button("Test"));
countryGrid.setHeaderSpans(ident);
countryGrid.draw();

Please help!

回答1:

Finally I found the way to add button to a HeaderSpan. Below is the code (Have omitted import statements for brevity):-

public class AdvancedListGrid extends ListGrid {
    public void setHeaderSpanButtons() {
        this.getAttribute("headerSpans");

        NodeList<Element> list = this.getElement().getElementsByTagName("td");
        int length = list.getLength();
        for(int index = 0; index < length; index++) {
            Element element = list.getItem(index);

            if(element.getInnerHTML().toString().equals("Identification")) {
                element.setInnerHTML(null);
                element.insertFirst(createHeaderSpanContents());
            }
        }
    }

    private Element createHeaderSpanContents() {
        HLayout hLayout = new HLayout();
        Button button = new Button("+");
        button.setHeight(20);
        button.setWidth(20);
        button.addClickHandler(new ClickHandler(){

            @Override
            public void onClick(ClickEvent event) {
                SC.say("Why did you click me?");
            }});

        Label title = new Label("Test Title");
        title.setWidth(70);
        title.setHeight(20);

        hLayout.addMember(button);
        hLayout.addMember(new LayoutSpacer());
        hLayout.addMember(title);

        return hLayout.getElement();
    }
}

The client class will call the AdvancedListGrid.setHeaderSpanButtons() method to add buttons to the header span. Of course you can customize the method to meet your needs.



回答2:

I'm testing it, as I need to put a Calendar in a HeaderSpan. Thanks for sharing your idea, it's of great help, although it took a while to set the correct imports.

A note : the setHeaderSpanButtons() method will only work if the datasource of the ListGrid is set. If it's not, no header at all is shown.

An improvement : you can add a break in the loop, no need to loop the whole NodeList:

if(element.getInnerHTML().toString().equals("Identification")) {
            element.setInnerHTML(null);
            element.insertFirst(createHeaderSpanContents());
            break;
        }

A question : what is the purpose of this line:

this.getAttribute("headerSpans");

And finally, it doesn't work for me - the span stays always as text "Identification". Any suggestions?

Thanks.



回答3:

Did you test it on IE? I tested in FF and it works fine, but I have problems when clicking around my app in IE. As far as I read, it is due to the mix of GWT and SmartGWT. So I guess it's better to use a ToolStrip like in this example: http://www.smartclient.com/smartgwt/showcase/#grid_appearance_preferences



回答4:

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.smartgwt.client.widgets.events.DrawEvent;
import com.smartgwt.client.widgets.events.DrawHandler;
import com.smartgwt.client.widgets.grid.ListGrid;

public class AdvancedListGrid extends ListGrid {
    public AdvancedListGrid() {

        // Create the HeaderSpan with title "Identification"

        addDrawHandler(new DrawHandler(){

            @Override
            public void onDraw(DrawEvent event) {
                insertCalendar();
            }});
    }

    public void insertCalendar() {
        for(Element element : DOMUtils.getElementsByTagName("td")) {

            if(element.getInnerHTML().equals("Identification")) {
                createCalendar(element);

            }
        }
    }

    public void createCalendar(Element element) {
        DOMUtils.removeAllChildNodes(element);

        // Create the SmartGWT calendar object. Say the object cal.

        element.setInnerHTML(cal.getInnerHTML());
    }
}

class DOMUtils {
    public static void removeAllChildNodes(Element element) {
        NodeList<Node> childList = element.getChildNodes();
        for(int childIndex = 0; childIndex < childList.getLength(); childIndex++) {
            element.removeChild(childList.getItem(childIndex));
        }
    }

    public static Element[] getElementsByTagName(String tagName)
    {
        JavaScriptObject elements = getElementsByTagNameInternal(tagName);
        int length = getArrayLength(elements);
        Element[] result = new Element[length];
        for (int i=0; i<length; i++)
        {
            result[i] = getArrayElement(elements, i);
        }
        return result;
    }

    private static native JavaScriptObject getElementsByTagNameInternal(String tagName)/*-{
    return $doc.getElementsByTagName(tagName);
  }-*/;

    private static native int getArrayLength(JavaScriptObject array)/*-{
    return array.length;
  }-*/;

    private static native Element getArrayElement(JavaScriptObject array, int position)/*-{
    return (position>=0 && position<array.length?array[position]:null);
  }-*/;
}


回答5:

Here's doing it without JSNI or DOM: This grid updates contents of the second span header with dynamic content when datasource is loaded. Alternately, you could use "onDraw" instead of "dataArrived", if the contents are static

import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.grid.HeaderSpan;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.events.DataArrivedEvent;
import com.smartgwt.client.widgets.grid.events.DataArrivedHandler;

public class MyGrid extends ListGrid {

    private HeaderSpan          oneHeaderSpan = new HeaderSpan("span one", new String[] { "a", "b", "c" });
    private HeaderSpan          twoHeaderSpan = new HeaderSpan("span two", new String[] { "d", "e", "f" });
    final private static String ONE_SPAN_ID   = "span1";
    final private static String TWO_SPAN_ID   = "span2";

    public MyGrid() {

        setID("MyGrid");
        setHeight100();
        setWidth100();
        setDataSource(MyDS);
        setHeaderSpans(oneHeaderSpan, twoHeaderSpan);
        oneHeaderSpan.setAttribute("spanId", ONE_SPAN_ID);
        twoHeaderSpan.setAttribute("spanId", TWO_SPAN_ID);
        setHeaderHeight(50);

        addDataArrivedHandler(new DataArrivedHandler() {
            @Override
            public void onDataArrived(DataArrivedEvent event) {
                Canvas headerSpans = Canvas.getById(getID() + "_headerSpan");
                // getPeers() did not work for IE
                for (Canvas peer : headerSpans.getParentCanvas().getChildren()) {
                    if (peer.getAttribute("spanId") != null && peer.getAttribute("spanId").equals(TWO_SPAN_ID)) {
                        peer.addChild(createHeaderSpanContents(event));
                    }
                }
            }
        });
    }

    private Canvas createHeaderSpanContents(DataArrivedEvent event) {

        // Your favorite Canvas here:
        Button button = new Button();
        button.setLayoutAlign(Alignment.CENTER);
        button.setHeight100();
        button.setWidth100();
        button.setTitle("+");
        return button;
    }
}

Using headerSpans.getParentElement().getChildren()) also works if you are on version of smartgwt preceding 4.1d



标签: smartgwt