Crud UI Add-on

Hello Alejandro,

are we able to do in memory sort to the grid?
and are we able to do access each elements(componets) in the form?

are we able to do in memory sort to the grid?
and are we able to do access each elements(componets) in the form?

I’d suggest doing any kind of sorting in the backend invoked by your CrudListener or FindAllCrudOperationListener implementations.

Hello Alejandro,

While using the CRUD UI in my project I came across a field which is of type java.sql.Time. Currently, it is being displayed with DatePicker. Are there any plans to add a separate component for storing the time (may be in hours)? It could be a number scroller or something.

While using the CRUD UI in my project I came across a field which is of type java.sql.Time. Currently, it is being displayed with DatePicker. Are there any plans to add a separate component for storing the time (may be in hours)? It could be a number scroller or something.

There’s a Time Picker mentioned in the roadmap. We could use it once it’s out. https://vaadin.com/roadmap. Meanwhile, you could implement your own component and use the setFieldProvider method to show it.

Hello Alejandro,

I have an issue with your add-on when I add a new item with the form, the new item will appear in the grid but, when I click on any item in this list, I got the error message : 'The provided value is not part of ComboBox: [Item Label]
'.

Have you any idea ? It looks like my ComboBox (filter or add/update popup) doesn’t refresh its content.

Charly Pichard:
Hello Alejandro,

I have an issue with your add-on when I add a new item with the form, the new item will appear in the grid but, when I click on any item in this list, I got the error message : 'The provided value is not part of ComboBox: [Item Label]
'.

Have you any idea ? It looks like my ComboBox (filter or add/update popup) doesn’t refresh its content.

Hi,

Hard to say without seeing some code, but might be related to equals and hashCode.

Alejandro Duarte:

Charly Pichard:
Hello Alejandro,

I have an issue with your add-on when I add a new item with the form, the new item will appear in the grid but, when I click on any item in this list, I got the error message : 'The provided value is not part of ComboBox: [Item Label]
'.

Have you any idea ? It looks like my ComboBox (filter or add/update popup) doesn’t refresh its content.

Hi,

Hard to say without seeing some code, but might be related to equals and hashCode.

Thank you, you showed me the way !
I forgot to add the equals and hashCode methods in my entities classes… :blush:

Charly Pichard:
Thank you, you showed me the way !
I forgot to add the equals and hashCode methods in my entities classes… :blush:

Glad to hear you fixed the problem!

Jason Tan:
Hi Alejandro. Thanks for the improvements to 1.5

I’ve found everything super simple to customise with apart from the cases of domain objects with nested objects with multiple fields (e.g. CRUD for a person object who has many addresses.

Can you advise on how i would go about creating forms for this sort of relationship:

class Person{
  String name;
  String lastname;
  List<Address> addresses;
}

I’ve tried using the formFactory.setFieldProvider to assign a custom popup window for filling in an address like so:

GridLayoutCrudFormFactory<Person> formFactory = new GridLayoutCrudFormFactory<>(Person.class, 2, 2);
        GridBasedCrudComponent<Person> crud = new GridBasedCrudComponent<>(
                Person.class);
        crud.setCrudFormFactory(formFactory);
        formFactory.setFieldProvider("address", ()-> new AddressPopup());
        addComponent(crud);

but the result is a IllegalArgumentException: Window is already attached to an application. So I’m clearly doing something wrong!

Thank you kindly,
Jason

Hi Alejandro,thank you in advance for your help.
I’m pretty new with Vaadin and i’m working with your CRUD add-on.
Now i’m facing same situation as the one described above and no error is fired during executions, but it seems no data is returned from AddressPopUp.

Here the code :

Into the main CRUD :

formFactory.setFieldProvider("indirizzi", ()-> new AddressPopUp());

The class declaration :

public class AddressPopUp extends CustomField<ArrayList<Address>> { }

.
.
.
The class return a button visible into the main CRUD form and correctly opens
a window with inner CRUD.
The object containing inner grid data is the layout.elenco you could see within
the following methods:

	@Override
	public ArrayList<Address> getValue() {			
		return layout.elenco;
	}
	@Override
	protected void doSetValue(ArrayList<Address> value) {			
		this.layout.elenco = value;	
	}

Unfortunately, as i said before, when i close inner window and save data in main CRUD there’s no trace
of what we saved into the inner and the update form doesn’t show data either.
I’m sure i’m missing something, could you please show me an AddressPopUp example ? (in Vaadin 8 would be perfect… )
Thank you again.

Hi Alejandro,thank you in advance for your help.
I’m pretty new with Vaadin and i’m working with your CRUD add-on.
Now i’m facing same situation as the one described above and no error is fired during executions, but it seems no data is returned from AddressPopUp.
It might be a problem with your implementation of CustomField. Are you actually callling AddressPopUp::setValue from somwhere? Try adding a breakpoint inside setValue and change the value of your custom field. Execution should stop at the breakpoint.

Alejandro, thank you for your kind reply.
Effectively i’m not sure if i’m doing all the things needed since i only call the AddressPopUp with :

formFactory.setFieldProvider("indirizzi", ()-> new AddressPopUp());

from within a CRUD UI similar to your example but i’m not calling AddressPopUp anywhere :frowning:

Doing this i correctly got a button and child CRUD UI correctly shows up.

To be more clear here follows the class code of “AddressPopUp” CustomField who’s real name is PopUpCodiceArticolo.

Thank you again !

public class PopUpCodiceArticolo extends CustomField<ArrayList<CodiceArticoloType>> {
    private static final long serialVersionUID = 2721197776543658373L;
    public CrudCodiceArticolo layout = new CrudCodiceArticolo(); // CRUD interface that correctly returns data in layout.elencoC
    private Window window ;
    private ArrayList<CodiceArticoloType> lista ;
    VaadinSession session = UI.getCurrent().getSession();

    @Override
    protected Component initContent() {
    	VerticalLayout v = new VerticalLayout();     
        v.addComponent(layout);
        Button okButton = new Button("Ok");
        okButton.setWidth("100%");
        okButton.addClickListener(new Button.ClickListener() {
			
			@Override
			public void buttonClick(ClickEvent event) {
				window.close();
			}
		});
        v.addComponent(okButton);
        window = new Window("Inserisci i codici Articolo", v);
        window.setModal(true);	// make window be correctly showed over the parent and waiting until close

        Button button = new Button("Codici Articolo"); 
        button.addClickListener(new ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
            	 getUI().addWindow(window);
            }
        });
        
        window.addCloseListener(new CloseListener() {
            private static final long serialVersionUID = -1936217938466658922L;

            public void windowClose(CloseEvent e) {
                try {
                	System.out.println("Scrivo : " + layout.elencoC.size());
                	// some stuff to do to send result back ?
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        });

        window.center();
        window.setWidth(null);
        layout.setWidth(null);
        layout.setMargin(true);
        return button;
    }

	@Override
	public ArrayList<CodiceArticoloType> getValue() {
		System.out.println("Valore letto " + layout.elencoC.size());
		return layout.elencoC;

	}


	@Override
	protected void doSetValue(ArrayList<CodiceArticoloType> value) {
		System.out.println("Valore settato ");
		this.layout.elencoC = value;				// seems to be never called

		
	}
}

You need to call PopUpCodiceArticolo::setValue at some point, otherwise the value is never set. Probably in the window close listener? But this is a question more about CustomField than the Crud UI component.

Perfect, it worked ! Thank you very much !
One last thing , if you allow me, how can i set some CRUD form input field as a XMLGregorianCalendar, like the linked bean field is? ( Not my choose, is a date format imposed by other components.)
I owe you a favor. :slight_smile:

Hello Alejandro,

I am using the Hibernate Validation to validate my UI fields. The built-in validations and custom field level validations are working perfectly fine. For one of the requirements I have created a custom class level validator but it does not seem to be working as expected. I have followed the steps as mentioned in the http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-class-level-constraints

I feel the validator class is not getting invoked. Can you please help me in this regards?

  • Annotation:
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Target({TYPE})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy= CreditCheckValidator.class)
public @interface CreditCheck {
	
	String message() default "Amount exceeds the credit limit!";
    
	Class<?>[] groups() default {};
    
    Class<? extends Payload>[] payload() default {};
}
  • Validator Class:
import java.math.BigDecimal;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
...

public class CreditCheckValidator implements ConstraintValidator<CreditCheck, Advance> {

	@Override
	public void initialize(CreditCheck constraintAnnotation) {
	}
	
	@Override
	public boolean isValid(Advance advance, ConstraintValidatorContext constraintContext) {
		if (advance == null) {
			return true;
		}
		
		boolean isValid;
		
		BigDecimal totalOutstandingAmt = new BigDecimal(0);
		Employee employee = advance.getEmployee();
		
		if(advance.getAdvanceAmount() != null)
			totalOutstandingAmt = totalOutstandingAmt.add(advance.getAdvanceAmount());

		isValid = employee.getCreditLimit().subtract(totalOutstandingAmt).doubleValue() > 10;
		
		if(!isValid) {
			constraintContext.disableDefaultConstraintViolation();
			constraintContext
					.buildConstraintViolationWithTemplate(constraintContext.getDefaultConstraintMessageTemplate())
					.addConstraintViolation();
		}
		return isValid;
	}
}

Good Evening Alejandro and thank you for your precious help.
Now i’m facing a strange behavior on Custom renderer ( Vaadin 8 ) and i’d like to ask you and advice.

I’ve created the three classes as suggested for client/server sides like these ones :

The call :
crud.getGrid().getColumn("condizioniPagamento").setRenderer( new TextRendererNew());

package .....client
public class TextRendererNew implements Renderer<String> {
    @Override
    public void render(RendererCellReference cell,
                       String text) {
        cell.getElement().setInnerText("--" + text + "--");
    }
}
package .....server
public class TextRendererNew extends AbstractRenderer<String> {
    public TextRenderer() {
        super(String.class);
    }
}
package ......connectors
@Connect(....server.TextRendererNew.class)
public class TextRendererNewConnector
       extends AbstractRendererConnector<String> {
    @Override
    public TextRendererNew getRenderer() {
        return (TextRendererNew) super.getRenderer();
    }
}

But i’m getting nothing, even if i clone exactly the TextRenderer class.
What i’m doing wrong ?
Thank you in advance for your help.

What is difference between
https://vaadin.com/directory/component/crud-ui-add-on
and
https://vaadin.com/directory/component/vaadin-crud

Лешик ツ:
What is difference between
https://vaadin.com/directory/component/crud-ui-add-on
and
https://vaadin.com/directory/component/vaadin-crud

Vaadin Crud is a commercial component maintained by Vaadin Ltd., the company. Crud UI is a free add-on maintained mostly by me.

Cheers.

Hey Alejandro, great addon man!!

What is the best way to handle a OneToMany Strings property o a class.

class Ship {
    @Column String name;
	
	@ElementCollection List<String> tags = new ArrayList<>();	
}

Would simple way would be to use a simple TextField and just process the data when generating the form it joins the names on the “,”, and when saving to the Pojo will to the reverse. Is this possible?

Thanks man

How add own render?
For example I have field instant

Gustavo Madruga:
Hey Alejandro, great addon man!!

What is the best way to handle a OneToMany Strings property o a class.

class Ship {
    @Column String name;
	
	@ElementCollection List<String> tags = new ArrayList<>();	
}

Would simple way would be to use a simple TextField and just process the data when generating the form it joins the names on the “,”, and when saving to the Pojo will to the reverse. Is this possible?

Thanks man

Yes, you can do that. Alternatively, you can implement a [custom field]
(https://vaadin.com/docs/v10/flow/binding-data/tutorial-flow-field.html) that transform a String to a List.