Loading...
Important Notice - Forums is archived

To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Product icon
TUTORIAL

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.

Adding Component Inside Table Header

Abhiram Giri
7 years ago Jul 10, 2015 11:01am

Hi,
I just tried to put component inside table header. I proceeded some what. In case of table field factory from server some components are sent to client to paint in side body. Like that I am sending some component to paint inside header. The component what I am trying to paint through LegacyPaint.paint(..). It is painting perfactly. But All the information for the component is not going to client for paint. for a text field I am attaching valluchange listener, for a combobox i added some item. But its not painting the items for combobox. I am attaching the addon project. Belows are my code standards. Any body please look into it.

I know Vaadin Grid Component is supporting those feature but it does not support the column resizing. I thought Why cant we customize the table to achieve this.

ExtTable.java   (Server Side Component)

Here setColumnComponent(String propertyId, Component component) will add component to the table column. If the a component is already added to the column it will unregister the old one and add the new one by registering it.

public void setColumnComponent(String propertyId, Component component) {
        if (singleColumnComponent.containsKey(propertyId)) {
            unregisterColumnComponent(singleColumnComponent.get(propertyId));
        }
        singleColumnComponent.put(propertyId, component);
        registerColumnComponent(component);
       
    }

public Component getColumnComponent(String propertyId) {
        return singleColumnComponent.get(propertyId);        
    }

registerColumnComponent(Component component) will register (set the parent to table object) the newly added component.

protected void registerColumnComponent(Component component) {
        getLogger().log(
                Level.FINEST,
                "Registered {0}: {1}",
                new Object{component.getClass().getSimpleName(),
            component.getCaption()});
        if (!equals(component.getParent())) {
            component.setParent(this);
        }
    }

unregisterColumnComponent(Component component) will remove the component from parent.

protected void unregisterColumnComponent(Component component) {
        getLogger().log(
                Level.FINEST,
                "Unregistered {0}: {1}",
                new Object{component.getClass().getSimpleName(),
            component.getCaption()});
        component.setParent(null);
        /*
         * Also remove property data sources to unregister listeners keeping the
         * fields in memory.
         */
        if (component instanceof Field) {
            Field<?> field = (Field<?>) component;
            if(field.getPropertyDataSource()!=null){
                field.setPropertyDataSource(null);
            }            
        }
    }

Finally the components are painted to client by the belows code

private void paintColumnComponents(PaintTarget target) throws PaintException {
        target.startTag("colComp"); 
        for (String colId : singleColumnComponent.keySet()) {
            target.startTag("headercomponent-" + columnIdMap.key(colId));
                target.addAttribute("componentcolumnid", columnIdMap.key(colId));
                Component c = singleColumnComponent.get(colId);
                LegacyPaint.paint(c, target);
            target.endTag("headercomponent-" + columnIdMap.key(colId));            
        }
        target.endTag("colComp");
    }

And this paintColumnComponents(PaintTarget target) is called as belows before painting the visible column.

paintColumnOrder(target);

        // Available columns
        paintAvailableColumns(target);
        [color=#EE82EE][b]paintColumnComponents(target);[/b][/color]
        paintVisibleColumns(target);

VExtScrolTable.java   (Client Side Widget)

The below code is gathering the widget sent from server to paint

Map<String, Widget> singleColumnComp = new HashMap<String, Widget>()
public void updateCellsComponentFromUIDL(UIDL uidl) {            
            for (final Iterator<Object> it = uidl.getChildIterator(); it
                    .hasNext();) {
                final UIDL cc = (UIDL) it.next();
                if (cc.getTag().startsWith("headercomponent-")) {
                    String cid = cc.getStringAttribute("componentcolumnid");
                    UIDL uidld = cc.getChildUIDL(0);
                    if (uidld != null) {
                        ComponentConnector connector = client
                                .getPaintable(uidld);
                        singleColumnComp.put(cid, connector.getWidget());
                    }
                }
            }
        }

The updateCellsComponentFromUIDL(UIDL uidl) is called before painting the columns in updateColumnProperties(UIDL uidl) like belows

public void updateColumnProperties(UIDL uidl) {
        updateColumnOrder(uidl);

        updateCollapsedColumns(uidl);

        UIDL vc = uidl.getChildByTagName("visiblecolumns");
        [b][color=#EE82EE]UIDL vc2 = uidl.getChildByTagName("colComp");        
        if (vc2 != null) {
            tHead.updateCellsComponentFromUIDL(vc2);
        }[/color][/b]
        if (vc != null) {
            tHead.updateCellsFromUIDL(vc);
            tFoot.updateCellsFromUIDL(vc);
        }

        updateHeader(uidl.getStringArrayAttribute("vcolorder"));
        updateFooter(uidl.getStringArrayAttribute("vcolorder"));
        if (uidl.hasVariable("noncollapsiblecolumns")) {
            noncollapsibleColumns = uidl
                    .getStringArrayVariableAsSet("noncollapsiblecolumns");
        }
    }

Then inside updateCellsFromUIDL(UIDL uidl) when creating the HeaderCell, I am adding those widget as an element to the column like this

public HeaderCell(String colId, String headerText) {
            cid = colId;

            setText(headerText);

            td.appendChild(colResizeWidget);

            // ensure no clipping initially (problem on column additions)
            captionContainer.getStyle().setOverflow(Style.Overflow.VISIBLE);

            td.appendChild(sortIndicator);
            [b][color=#EE82EE]td.appendChild(compCont);
            if(singleColumnComp.containsKey(cid)){
                Widget w=singleColumnComp.get(cid);
                compCont.removeAllChildren();
                compCont.appendChild(w.getElement());                
            }[/color][/b]
            td.appendChild(captionContainer);

            DOM.sinkEvents(td, Event.MOUSEEVENTS | Event.ONDBLCLICK
                    | Event.ONCONTEXTMENU | Event.TOUCHEVENTS);

            setElement(td);

            setAlign(ALIGN_LEFT);
        }

Here compCont is a DIV element which acts like a container for the component.

Here I am unable to replicate what may be the mistake. I have attached full project. Please anybody help me to find a solution to this.

 

Abhiram Giri
7 years ago Jul 13, 2015 5:19am