Set column read only on Sql Container backed Table

Hello all,
I tried to search for an answer quite a bit before posting, as i know there is nothing more frusturating than answering the same thing over and over, but I couldn’t find anything quite the same.

I have a sql container backed table which I am using to allow entering new rows into a database table, and edit existing rows. New rows I want to allow users to change any data, existing rows I want them to be able to edit only some of them.

What I have done kinda works… It’s good until you get to ordering columns, or sorting. Once you do either of those, things go back to
not
read only.

Is there a better way for me to do this??

private TableQuery tq;
private SQLContainer sq;
private Table table;

tq = new TableQuery("pricing", DatabaseFactory.getInstance().getVaadinPool());

        sq = null;
        try {
            sq = new SQLContainer(tq);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        setReadOnly(sq, "pricing_cd");

table = new Table();
        table.setContainerDataSource(sq);
        table.setImmediate(true);
        table.setEditable(true);
        table.setBuffered(true);
        table.setColumnReorderingAllowed(false);
        table.addHeaderClickListener(new Table.HeaderClickListener() {
            
            @Override
            public void headerClick(HeaderClickEvent event) {
                // TODO Auto-generated method stub
                setReadOnly(sq, "pricing_cd"); //this does not work
                table.refreshRowCache();
            }
        });

save = new Button("Save",
                new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                try {
                    sq.commit();
                    setReadOnly(sq, "pricing_cd"); //this works
                    table.refreshRowCache();
                    Notification.show("Pricing saved.");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    Notification.show("Pricing could not be saved.\n Both Pricing_Description and Pricing_CD must have values, and Pricing_CD must be unique.", Type.ERROR_MESSAGE);
                    
                    for(Object item : table.getItemIds())
                    {
                        if(item.toString().equals("Temporary row id") &&
                        (table.getItem(item).getItemProperty("pricing_description").getValue() == null ||
                        table.getItem(item).getItemProperty("pricing_cd").getValue() == null)) //remove uncommitted rows from the table if they haven't entered any data
                        {
                            table.removeItem(item);
                        }
                            
                    }
                }
            }
        });
        save.setImmediate(true);
        save.setWidth("65px");
        save.setHeight("25px");

private void setReadOnly(Container container, String propertyID)
    {
        for(Object item : container.getItemIds())
        {
            container.getContainerProperty(item, propertyID).setReadOnly(true);
        }
        
    }

Hi,

I think operations such as sorting will refresh the SQLContainer’s internal cache completely, which will override your read-only settings. Unfortunately the container was not designed for such settings, so it might be that this is not doable.

One thing you could try is to subclass the SQLContainer, and override the getContainerProperty method. Then you could check if the propertyId parameter matches your read-only property and set the read-only to be true before returning the Property. Disclaimer: I did not try this, but seems to me it could work.

Alright, that sounds like an idea… will probably give it a try.

Do you know of a listener I could add which would trigger on sorting or column order changing?

Found a simple solution it seems… kinda hackish and I don’t love it, but i’d like to at least post what I found here in case someone else needs to do something similar.

I simply added a listener to the sql container.

I now check to make sure that the value in the field is not null before setting read only on the property (only set it on non-null values), and I added an ItemSetChangeListenerto the Sql Container. I removed the header click listener on the table, and I removed the call to set read only on save (as it calls the ItemSetChangeListener when commiting changes).

sq.addItemSetChangeListener(new ItemSetChangeListener() {

            @Override
            public void containerItemSetChange(ItemSetChangeEvent event) {
                // TODO Auto-generated method stub
                setReadOnly(sq, "pricing_cd");
            }
        });

Thanks Adam.

I was figuring out the same problem with SQLContainer. This hack you posted for now solved my problem as well. Cheers!