Certain cells in a table

I have a table. Added few items to it. Now, I want to make only certain cell’s editable. any help in how to achieve is appreciated

The code I have is
I want only Subscriber, Bulk Order and Has Unix Id cells to be editable

Note that I have a table like this

COLUMN NAME DESCRIPTION

First Name abcd
Last Name efgh
Subscriber Y
Has Unix Id Y
Bulk Y

and I want only the cells with “Y” to be editable and have yes or no values



		final Table userDetailsTable = new Table();
		final OrdersCopa order = new OrdersCopa();
		final Button edit = new Button("Edit User");
		Button showOrdersButton = new Button("Show User Orders");

		String emailString = "";
		final UserReg row = ((UserReg) itemId);

		final Window userDetailsSubWindow = new Window("User Details for: " + row.getLastName());

		userDetailsTable.addContainerProperty("COLUMN NAME", String.class, null);
		userDetailsTable.addContainerProperty("DETAILS", String.class, null);
		userDetailsTable.addItem(new Object[] { "User Key", row.getUserKey() }, new Integer(1));
		userDetailsTable.addItem(new Object[] { "First Name", row.getFirstName() }, new Integer(2));
		userDetailsTable.addItem(new Object[] { "Last Name", row.getLastName() }, new Integer(3));
		userDetailsTable.addItem(new Object[] { "User ID", row.getUserId() }, new Integer(4));
		userDetailsTable.addItem(new Object[] { "Bulk Order", row.getBulkOrder() }, new Integer(5));
		userDetailsTable.addItem(new Object[] { "Date Last On", row.getDateLastOn() }, new Integer(6));
		userDetailsTable.addItem(new Object[] { "Subscriber", row.getSubscriber() }, new Integer(8));

		for (UserEmail email : row.getUserEmails()) {
			emailString += email.getEmailAddress().trim() + "[Email Type: " + email.getEmailType() + "]
" + ",";
		}
		userDetailsTable.addItem(new Object[] { "Emails(s)", emailString.substring(0, emailString.length() - 1) }, new Integer(7));
		userDetailsTable.addItem(new Object[] { "Subscriber", row.getSubscriber() }, new Integer(8));
		userDetailsTable.addItem(new Object[] { "Archive Manager", row.getArchive() }, new Integer(9));
		userDetailsTable.addItem(new Object[] { "Create Date", row.getCreateDate() }, new Integer(10));
		userDetailsTable.addItem(new Object[] { "Number of Accesses", row.getNumberOfAccesses() }, new Integer(11));
		userDetailsTable.addItem(new Object[] { "Has Unix id", row.getUnix() }, new Integer(12));

		userDetailsTable.setSizeFull();
		userDetailsSubWindow.addComponent(userDetailsTable);
		userDetailsSubWindow.addComponent(showOrdersButton);
		userDetailsSubWindow.addComponent(edit);

		tableReference.getApplication().getMainWindow().addWindow(userDetailsSubWindow);

		userDetailsSubWindow.setModal(true);
		userDetailsSubWindow.setClosable(true);
		userDetailsSubWindow.setHeight("550px");
		userDetailsSubWindow.setWidth("1000px");

		// show user order button click listener
		showOrdersButton.addListener(new Listener() {

			@Override
			public void componentEvent(Event event) {
				System.out.println("The Users Item Id is : " + row.getUserId());
				order.setUserId(row.getUserId());
				ordersCopaManager.getOrdersByCriteria(order);
				// ordersCopaManager.findUsers(user);
				SpringVaadinApplication spa = (SpringVaadinApplication) tableReference.getApplication();
				spa.refreshOrdersSearchResultsTable(order);
				spa.getMainWindow().removeWindow(userDetailsSubWindow);

			}
		});

		edit.addListener(new Listener() {

			@Override
			public void componentEvent(Event event) {

				System.out.println("The SUBSCRIBER: " + userDetailsTable.getItem("subscriber"));
			}
		});

	}

Never tried it out, but if you set your table editable and replace the two non-editable columns by GeneratedColumns of type Component and return there always a Label, it could work.

Hi,

You have to add a TableFieldFactory to the table


table.setTableFieldFactory(new TableFieldFactory() {
			
			@Override
			public Field createField(Container container, Object itemId,
					Object propertyId, Component uiContext) {
				
				if("Subscriber Y".equals(propertyId)){
					//creating a new Field (TextField, ComboBox,...)
					return new TextField();
				}
				
				// Do the same with all your editable properties.
				
				// Return null for all properties you want NOT editable.
				return null;
			}
		});

and then set the table in editable mode with table.setEditable(true)

Hope it’s help.

Eric thanks a lot. The approah of TableFieldFactory worked. Heres the working code. I have another question now. How do I add validation to those 4 fields ? Below is the code executed when someone clicks on the edit button, this will convert the 4 fields into textfields. I want to add some validation to those.



// edit the user
		edit.addListener(new Listener() {

			@Override
			public void componentEvent(Event event) {

				userDetailsTable.setTableFieldFactory(new TableFieldFactory() {

					@Override
					public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
						final TextField tf = new TextField();
						System.out.println(" THE ITEM ID IS " + itemId);

						if ("COLUMN NAME".equals(propertyId)) {
							tf.setReadOnly(true);
						} else {
							tf.setData(itemId);
						}

						for (int i = 1; i <= 8; i++) {
							if (itemId.equals(i)) {
								tf.setReadOnly(true);
							}
						}

						return tf;
					}
				});

				userDetailsTable.setEditable(true);
			}
		});


tf.addValidator(Validator) inside the createField()

thank you. i did that. as shown below. but i want to


		// edit the user
		edit.addListener(new Listener() {

			@Override
			public void componentEvent(Event event) {

				userDetailsTable.setTableFieldFactory(new TableFieldFactory() {

					@Override
					public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
						final TextField tf = new TextField();
						System.out.println(" THE ITEM ID IS " + itemId);

						// set the entire column read only
						if ("COLUMN NAME".equals(propertyId)) {
							tf.setReadOnly(true);
						} else {
							tf.setData(itemId);
						}

						// set the first 8 fields in second column read only
						for (int i = 1; i <= 8; i++) {
							if (itemId.equals(i)) {
								tf.setReadOnly(true);
							}
						}

						tf.addValidator(new StringLengthValidator("Takes only one character (Y or N)", 1, 1, false));
						tf.setComponentError(new UserError("This fields takes only Y or N"));
						tf.setValidationVisible(true);
						tf.setImmediate(true);
						return tf;
					}
				});

				userDetailsTable.setEditable(true);
			}
		});

                 // save the user edit
		save.addListener(new ClickListener() {

			@Override
			public void buttonClick(ClickEvent event) {

                                  /*  How to validate the form here? or fields here?
                                  */

			}
		});



I want to know how to validate the fields in the save button click. if the fields are correctly entered then i want to continue with my query running or some actions.
I also don’t see a exclamation mark when I enter something else in the fields. But when I hover over the field i see the message. I am not sure why the exclamation mark is not showing up

I don’t think that you can validate the table directly, but what you can do is make a List fields; in that class, and in createField add every field into it, and in the save action do something like:

for(Field field : fields) {
  if(!field.isValid()){
    throw new SomeException(); // or store a boolean or something
  }
}

notice that if you toggle the editable mode, remove the table or something like that, then the createField will be called for all cells again, and you have to clear you list before hand. Otherwise you have old fields in the list.

If I remember correctly, this can also happen e.g. when scrolling in a table that does not fit in the client side buffer at once, so always be careful if keeping track of such generated fields. I cannot recall right now if attach() and detach() for the fields gets called even though a Table is (currently) not a ComponentContainer.

As it is indeed difficult to track those field correctly (BTW: Are there plans to make validating editable tables easier? It is a pretty common task…), one could add a ValueChangeListener to the fields instead of a Validator. In that Listener you can do a “manual” validation and add / remove a ComponentError to / from the field if necessary. Not a nice, but a secure solution as you do not have to think about synchronizing any datastructure.