Difficulty creating a Custom Grid Renderer to mimic a TextField

I tried that. Interestingly enough, when I try using that on the text column (which happens to be the third column in the strange reorganization it does) I only see the first two columns, complete with data. The rest of the columns go missing. I tried it with various others and similar occurances happen.

This needs more proper debugging, which I plan to try shortly after lunch.

I have spent a few hours trying various things and so far am no closer to figuring out what’s going on.

In short, I haven’t been able to successfully setup SuperDevMode so far. I came across
this post on how to do it in IntelliJ
, but haven’t quite gotten it to work.

I am getting the impression that my environment is to blame and here’s why. I stripped down my Container to two integers and two strings. Everything else was removed. Likewise, I removed all code from my page involving anything tricky with the grid, leaving only its initialization. Without adding the Renderer, things work fine. However, once I add the renderer, even in its most stripped version, I get the exact same error … The exception I posted yesterday morning.

Interestingly enough, when debugging the application, the initialization works fine, and the data enters the grid fine. This exception only comes up when I try to view the page that the grid is on. So, whatever this is, it is entirely client side. I tried tracing the Javascript code to see what’s going on, but that led me nowhere. That code is so obfuscated that understanding it is beyond my ability (or more precisely, my patience).

I will try again to get SuperDevMode working a bit later, but I am curious, could this problem simply be something wrong with my generated WidgetSet? Is there something I can do to validate that it is correctly being built? Initially I was having some issues upgrading to Vaadin 7.4.7 from 7.3.x because of some ordering problems in my pom. Could this be the case here, too?

It could be connected to the Widgetset.
A few things you could try:

  • Try using a standard Vaadin Renderer like e.g. the ButtonRenderer on a Column and see if you get the same errors. If that’s the case your project is definetely the problem
  • Remove ever generated widgetset and client side gwt files/folders from your project and recompile + rebuild the entire project.
  • Create a new fresh project and try the Custom Renderer with a simple Grid (like the one example i posted). If it doesn’t work there you IDE might have a problem and you might want to try a newer version or a different one
  • If the last thing works try adding your source code one step after the other to see if it still works. If you eventually run into problems after e.g. adding a certain add-on you know what might cause the problem




So, it looks like the problem is in my IDE.

When trying a standard renderer in my grid, everything worked fine. I then blew away everything generated and rebuilt the project, and again I saw the same problem.

Then, I created a very very basic vaadin project from scratch consisting of the following code (but using my copied classes)

public class MyUI extends UI {

    @Override
    protected void init(VaadinRequest vaadinRequest) {
        final VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        setContent(layout);

        ArrayList<ComplexModuleData> complexes = new ArrayList<>();
        ComplexModuleData data = new ComplexModuleData();
        data.setCt(0);
        data.setFundid(1);
        data.setFundname("TEST FUND");
        data.setTicker("ASDF12354");
        complexes.add(data);
        BeanItemContainer<ComplexModuleData> container = new BeanItemContainer<>(ComplexModuleData.class, complexes);
        Grid complexGrid = new Grid(container);
        complexGrid.getColumn("fundname").setRenderer( new GridEditableRenderer() );

        layout.addComponent(complexGrid);
    }

    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
    @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
    public static class MyUIServlet extends VaadinServlet {
    }
}

The ComplexModuleData is a simple POJO consisting of just those 4 fields.

… and I see the same problem. Remove the renderer, everything works great. Set the renderer to a standard renderer, and again everything works great.

My IDE is IntelliJ Ultimate 13.1.5. I will try upgrading to the latest community version next week (or maybe over the weekend) and see if that helps. If you have any other ideas, I would be happy to hear them. Otherwise, I will let you all know how things go.

Maybe your widgetset compilation is buggy. Updating your IDE might help with that but you should also check if you maybe have an old Vaadin plugin or an old gwt or Java version set up for your project.
Other then that you should run the app in Dev mode and/or with detailed or pretty widgetset compilation to see what the error actually looks like.

So … that didn’t work. I didn’t want to mess with my machine, so I got a new machine to run a test on. The test was very simple, and is copied below.

I’m not really sure what to do about this. I would love to figure this out, simply for sport, but given that my existing code works I am leaning towards just waiting until 7.6 and take it from there.

In case you guys are curious, here’s the code I am using (the classes were copied wholesale from the posts above more or less)

package testing;

import javax.servlet.annotation.WebServlet;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.annotations.Widgetset;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.*;
import com.vaadin.ui.Button.ClickEvent;
import testing.ui.GridEditableRenderer;

import java.util.ArrayList;

/**
 *
 */
@Theme("mytheme")
@Widgetset("testing.MyAppWidgetset")
public class MyUI extends UI {

    @Override
    protected void init(VaadinRequest vaadinRequest) {
        final VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        setContent(layout);

        ArrayList<ComplexModuleData> complexes = new ArrayList<>();
        ComplexModuleData data = new ComplexModuleData();
        data.setCt(0);
        data.setFundid(1);
        data.setFundname("TEST FUND");
        data.setTicker("ASDF12354");
        complexes.add(data);
        BeanItemContainer<ComplexModuleData> container = new BeanItemContainer<>(ComplexModuleData.class, complexes);
        Grid complexGrid = new Grid(container);
        complexGrid.getColumn("fundname").setRenderer( new GridEditableRenderer() );

        layout.addComponent(complexGrid);
    }

    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
    @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
    public static class MyUIServlet extends VaadinServlet {
    }
}

and here’s the POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>testing</groupId>
    <artifactId>vaadincore</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>vaadincore</name>

    <properties>
        <vaadin.version>7.5.1</vaadin.version>
        <vaadin.plugin.version>${vaadin.version}</vaadin.plugin.version>
        <jetty.plugin.version>9.2.3.v20140905</jetty.plugin.version>
        <project.source.version>1.7</project.source.version>
        <project.target.version>1.7</project.target.version>
        <project.encoding>UTF-8</project.encoding>
    </properties>

    <repositories>
        <repository>
            <id>vaadin-addons</id>
            <url>http://maven.vaadin.com/vaadin-addons</url>
        </repository>
        <repository>
            <id>vaadin-snapshots</id>
            <url>https://oss.sonatype.org/content/repositories/vaadin-snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <version>${vaadin.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-server</artifactId>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-push</artifactId>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-client</artifactId>
            <scope>provided</scope>
        </dependency>
        <!--
          Needed when using the widgetset optimizer (custom ConnectorBundleLoaderFactory).
          
          For widgetset compilation, vaadin-client-compiler is automatically added on the
          compilation classpath by vaadin-maven-plugin so normally there is no need for an
          explicit dependency.
        -->
        <!--
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-client-compiler</artifactId>
            <scope>provided</scope>
        </dependency>
        -->
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-themes</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <encoding>${project.encoding}</encoding>
                    <source>${project.source.version}</source>
                    <target>${project.target.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <encoding>${project.encoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                    <!-- Exclude some unnecessary files generated by the GWT compiler. -->
                    <packagingExcludes>WEB-INF/classes/VAADIN/gwt-unitCache/**,
                        WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**</packagingExcludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-maven-plugin</artifactId>
                <version>${vaadin.plugin.version}</version>
                <configuration>
                    <extraJvmArgs>-Xmx512M -Xss1024k</extraJvmArgs>
                    <webappDirectory>${basedir}/target/classes/VAADIN/widgetsets</webappDirectory>
                    <draftCompile>false</draftCompile>
                    <compileReport>false</compileReport>
                    <style>OBF</style>
                    <strict>true</strict>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>update-widgetset</goal>
                            <goal>compile</goal>
                            <!-- disabled by default to use on-the-fly theme compilation -->
                            <!-- <goal>compile-theme</goal> -->
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.4</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.6.1</version>
                <!-- Clean up also any pre-compiled themes -->
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>src/main/webapp/VAADIN/themes</directory>
                            <includes>
                                <include>**/styles.css</include>
                                <include>**/styles.scss.cache</include>
                            </includes>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>

            <!-- The Jetty plugin allows us to easily test the development build by
                running jetty:run on the command line. -->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>${jetty.plugin.version}</version>
                <configuration>
                    <scanIntervalSeconds>2</scanIntervalSeconds>
                </configuration>
            </plugin>
        </plugins>

        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
                <!-- TODO Remove when http://dev.vaadin.com/ticket/14924 is resolved -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>com.vaadin</groupId>
                                        <artifactId>
                                            vaadin-maven-plugin
                                        </artifactId>
                                        <versionRange>[7.1.11,)</versionRange>
                                        <goals>
                                            <goal>resources</goal>
                                            <goal>update-widgetset</goal>
                                            <goal>compile</goal>
                                            <goal>compile-theme</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

    </build>

</project>

I am assuming that we all are talking about behavior on Tomcat specifically?

@Dan just out of curiousity I tried your UI with a new Ivy Project, a simple Bean as ComplexModelData and my TextFieldRenderer and it worked totally fine without problems…i have absolutely no idea why you’re having such problems with it (though it could be the POJO)
If you want i can attach the Project.

@Blanford: Not really. This is a problem with custom Renderers in a specific project. Shouldn’t be Server-specific.

Hi Marius. I never did figure out what caused the problem, I moved onto the Vaadin 7.6 alpha release instead. This caused a whole slew of other problems … but we’ll get to those in a separate thread.

Just reply for someone encountered same problems. I tried to build a custome grid renderer with custome layout, after using the code posted by Marius Reinwald in this thread, i encountered the error in the browser.

In my case, it seemed that the connector i build was not compiled ( u can check you mvn package log for it). Then this doc, https://vaadin.com/docs/-/part/framework/clientside/clientside-widget.html says “The client-side source code must be contained in a client package under the package of the descriptor file, which is covered later”.

After putting the code in the client package of the descriptor file, the connector was compiled. The renderer worked.

So for the one who try to make a custome renderer, the things u need to know is

  1. Grid Renderer: Client-widget(if u need custom layouts in front), client-renderer, connetor, server-renderer
  2. client-side things need to be compiled should be under the package of the descriptor file, for the descriptor file defination, see https://vaadin.com/docs/-/part/framework/clientside/clientside-module.html, so the final code structure should like something like this:https://vaadin.com/wiki/-/wiki/Main/Creating%20a%20simple%20component

These things fused me for about whole two days , wish the others can get help from it .

Check this repository for example. It has text field renderer, which implements custom event that can be catched when data has been edited, and needs to be e.g. commited to data base.

https://github.com/bonprix/grid-renderers-collection-addon

Thanks, that helped. I’ll be back when I run into more trouble. Very much appreciated!
Tôi rất yêu hà nội vì thế tôi đã mở công ty
thiết kế website chuyên nghiệp hà nội
và sống ở đó và phát triển các
dịch vụ thiết kế website chuyên nghiệp
giúp đỡ các bạn trẻ đam mê
kinh doanh nhỏ
hay
kinh doanh tại nhà
để khởi nghiệp. Hầu hết các dịch vụ web của tôi đều được khách hàng đánh giá cao về chất lượng như:
Thiết kế web du lịch
chuyên nghiệp,
thiết kế website tin tức
,
thiet ke web di dong
,
thiết kế website theo yêu cầu
,
thiết kế website khách sạn
,
thiet ke web bat dong san
,… Chính thành công của khách hàng đã làm cho chúng tôi có động lực và niềm tin để xây dựng và đẩy mạnh hơn nữa dịch vụ làm website giá rẻ tại Hà Nội nói riêng và trên toàn quốc nói chung. Xin cảm ơn

I’m facing the same issue but the weirdest part is that if i try running my app in superdevmode the textfieldrenderer works fine but if i deploy the war file to a tomcat container, the grid is not rendering correctly. My guess is that maybe my compilation configuration is wrong. Please find below my configuration. Any help is appreciated it

 <plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<version>7.4.4</version>
<configuration>
<extraJvmArgs>-Xmx512M -Xss1024k</extraJvmArgs>
<!-- <runTarget>mobilemail</runTarget> -->
<!-- We are doing "inplace" but into subdir VAADIN/widgetsets. This
way compatible with Vaadin eclipse plugin. -->
<webappDirectory>${basedir}/src/main/webapp/VAADIN/widgetsets
</webappDirectory>
<hostedWebapp>${basedir}/src/main/webapp/VAADIN/widgetsets
</hostedWebapp>
<!-- Most Vaadin apps don't need this stuff, guide that to target -->
<persistentunitcachedir>${basedir}/target/tmp/gwt-unitCache</persistentunitcachedir>
<!-- Compile report is not typically needed either, saves hunreds of
mb disk -->
<compileReport>false</compileReport>
<noServer>true</noServer>
<style>PRETTY</style>
<!--<style>OBF</style>-->
<strict>true</strict>
<runTarget>http://localhost:8080</runTarget>
</configuration>
<executions>
<execution>
<!-- <configuration> if you don't specify any modules, the plugin will
find them <modules> <module>com.vaadin.demo.mobilemail.gwt.ColorPickerWidgetSet</module>
</modules> </configuration> -->
<goals>
<goal>resources</goal>
<goal>update-widgetset</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>

You seem to have Vaadin version 7.4.4. which is quite old. The Grid was introduced in 7.4. and since then until todays 7.7.3 there has been bug fixes to Grid almost all releases of the framework. So I warmly recommend to retry with newer version.

I tried with the new version and it didn’t work. Is there any specific package structure i should use? As of right now I have the following files:

com/mycompany/renderers/MyRenderer.java

public class MyRenderer<T> extends ClickableRenderer<T> { public OwsTextFieldRenderer(){ super((Class<T>)Object.class); } } com/mycompany/renderers/client/MyRendererConnector.java

import com.google.gwt.core.client.GWT;
import com.vaadin.client.connectors.AbstractRendererConnector;
import com.vaadin.client.renderers.Renderer;
import com.vaadin.client.renderers.WidgetRenderer;
import com.vaadin.client.ui.VTextField;
import com.vaadin.client.widget.grid.RendererCellReference;
import com.vaadin.shared.ui.Connect;


@Connect(MyRenderer.class)
public class MyRendererConnectorextends AbstractRendererConnector<String> {


    public class MyClientRenderer extends WidgetRenderer<String,VTextField> {

        public MyClientRenderer(){

        }

        @Override
        public VTextField createWidget() {
            VTextField textField = GWT.create(VTextField.class);

            return textField;
        }

        @Override
        public void render(RendererCellReference rendererCellReference, String s, VTextField textBox) {
            textBox.setText(s);

        }
    }

    @Override
    protected Renderer<String> createRenderer() {
        return new MyClientRenderer();
    }

    @Override
    public MyClientRenderer getRenderer() {
        return (MyClientRenderer) super.getRenderer();
    }

}

com/mycompany/renderers/AppWidgetSet.gwt.xml

When i compile the widgetset in my web project i see it’s able to find the widgetset but when i try to set the renderer in the grid the column is removed from the grid. I debugged the application using superdev move and i found there is a class cast exception thrown in the following code in the GridConnector class. So far I cant understand how it’s throwing the class cast exception so any idead would be helpful. Thanks

private void addColumnFromStateChangeEvent(GridColumnState state) {
        GridConnector.CustomGridColumn column = new GridConnector.CustomGridColumn(state.id, (AbstractRendererConnector)state.rendererConnector);
        this.columnIdToColumn.put(state.id, column);
        this.getWidget().addColumn(column);
        this.columnOrder.add(state.id);
    }

I am curious, but why are you trying to render a textfield when the Grid has a native editor that works like a textfield? Is there some feature you need to take advantage of?

If not, I would try a simpler approach, and one that is more elegant. What works best for me (in most cases) is setting the following:

grid.setImmediate(true);
grid.setEditorEnabled(true);
grid.setEditorBuffered(false);

Then, when needing to watch for editor movement, I implemented the following listeners:

[code]
grid.addEditorListener(new Grid.EditorListener() {
@Override
public void editorOpened(Grid.EditorOpenEvent editorOpenEvent) {
ModuleData row = (ModuleData) editorOpenEvent.getItem();
complexGrid.select(row);
App.EVENT_BUS.post(new GridEnableEvent(getSession().getSession().getId(), false));
}

@Override
public void editorMoved(Grid.EditorMoveEvent editorMoveEvent) {
    ModuleData row = (ModuleData) editorMoveEvent.getItem();
    complexGrid.select(row);
}

@Override
public void editorClosed(Grid.EditorCloseEvent editorCloseEvent) {
    App.EVENT_BUS.post(new GridEnableEvent(getSession().getSession().getId(), true));
}

});
[/code]I have specific events that need firing when the Grid goes in and out of editing mode, but maybe you don’t need that.

Also, for specific columns that I care an especially large amount for, I do something like the following:

TextField valueField = new TextField();
grid.getColumn("valueColumn").setEditorField(valueField);

Now you can set whatever TextField properties you want to the valueField (such as addValueChangeListener, addShortcutListener, addBlurListener or whatever you so desire … coincidentally, not all TextField event listeners work properly, but most do)

That was my solution, up until a few weeks ago when the Vaadin team put together a very impressive piece of code,
GridFastNavigation Add-on
. This is a very versatile editor for the Grid that has helped us a great deal, but that’s an entirely different conversation.

… after clicking submit I just realized a major flaw in my code. That was all developed for Vaadin 7.6 alpha … so, it will not work too well in later versions. The tail end of my comment, GridFastNavigation, was the workaround to later versions that gave us the funcationlity we needed.

Sorry about that.

We have a requirement where we need to have the enable the multiple selection and then the user will hit a button and start editing only the rows that have previously selected, maybe the inline editing could work but i wanted to add a textfield to be able to show or hide depending on a property. At the beginning i thought this was the way to go but i think i need to go back to the drawing board. Thanks

You want to enable the editor in multiple rows at once? I don’t know if you can do that in a Grid. I think you may need to use a Table. I am no Vaadin expert, but I have yet to come across a way to edit multiple rows at once in a Grid. A Table, on the other hand, is a bit easier … so long as you aren’t dealing in large numbers of rows. The table slowed down a great deal when we broke 1000 rows given our requirements, not sure how it will fare with you.

Here’s a thought, what if you were to allow them to select multiple rows, but when they click the “Edit” button a modal popup would appear with only those rows in a table that is in full editing mode? May be easier, and you won’t need to deal with any Renderers.

Hi Esau,

I would implement your idea roughly as follows. First you have Grid with all rows and there you have multiselect. You probably want to add an edit button or something like that in your UI. Once clicked the master Grid is replaced with new Grid which has only the rows you selected in its container. Then you can use Grid unbuffered mode editor to edit the content of the Grid. In this view mode edit button is replaced with save and cancel buttons. Once you click either of those, you will replace sub Grid with the master Grid again.

Br. Tatu