Closed ugurdoksan closed 4 years ago
Hi @ugurdoksan ,
Thanks for reporting this. But I am not sure that I understand you or not. May i ask you to provide a sample project which can reproduce the bug?
You may fork this project base https://github.com/vaadin/skeleton-starter-flow
Hi @ZheSun88 , Here is the all code for reproducing problem:
` @Route( "" ) @PWA( name = "Project Base for Vaadin Flow", shortName = "Project Base" ) public class MainView extends VerticalLayout {
public MainView( ) {
add( new Button( "Click me", event -> {
ProductActivityDto dto = new ProductActivityDto( );
ProductActivityDialog dlg = new ProductActivityDialog( dto );
dlg.addOpenedChangeListener( e -> {
if( !e.isOpened( ) ) Notification.show( "Saved RegisterDate: " + dto.getRegisterDate( ) );
} );
} ) );
}
} `
` public class ProductActivityDialog extends Dialog {
private VerticalLayout vl;
private PhiDateTimePicker dtpRegisterDate;
private Binder<ProductActivityDto> binder;
public ProductActivityDialog( ProductActivityDto bean ) {
setCloseOnOutsideClick( false );
vl = new VerticalLayout( );
vl.setPadding( false );
add( vl );
//
initForm( );
binder = new Binder<>( ProductActivityDto.class );
binder.setBean( bean );
//
bindForm( );
open( );
}
private void initForm( ){
dtpRegisterDate = new PhiDateTimePicker( );
dtpRegisterDate.setLabel( "Date" );
dtpRegisterDate.setRequiredIndicatorVisible( true );
dtpRegisterDate.setWidth( "250px" );
vl.add( dtpRegisterDate );
addButtonBar( );
}
private void addButtonBar( ){
Button btnCancel = new Button( "Cancel" );
btnCancel.addClickListener( e -> close( ) );
btnCancel.setWidth( "50%" );
Button btnSave = new Button( "Save" );
btnSave.addClickListener( e -> createOrUpdate( ) );
btnSave.setWidth( "50%" );
HorizontalLayout hl = new HorizontalLayout( btnCancel, btnSave );
hl.setWidth( "100%" );
vl.add( hl );
}
protected void createOrUpdate( ){
if( !binder.validate( ).isOk( ) ) return;
// ProductActivityService.getInstance( ).save( bean );
// if( bean.getIdProductActivity( ) == null ) PhiV.showInfoCreate( );
// else PhiV.showInfoUpdate( );
close( );
}
private void bindForm( ){
binder.forField( dtpRegisterDate ).asRequired( ).bind( ProductActivityDto::getRegisterDate, ProductActivityDto::setRegisterDate );
}
}
`
`
public class PhiDateTimePicker extends CustomField
private DatePicker datePicker;
private TimePicker timePicker;
public PhiDateTimePicker( ) {
datePicker = createDatePicker( "", "60%", false, null );
datePicker.getElement( ).getStyle( ).set( "min-width", "0px" );
timePicker = createTimePicker( "", "40%", false, LocalTime.of( 0, 0 ) );
timePicker.getElement( ).getStyle( ).set( "min-width", "0px" );
add( datePicker, timePicker );
}
private DatePicker createDatePicker( String label, String width, boolean removeMargin, ZonedDateTime value ){
DatePicker dp = new DatePicker( label );
dp.setRequiredIndicatorVisible( true );
if( width != null ) dp.setWidth( width );
if( removeMargin ) dp.getStyle( ).set( "margin", "0px" );
dp.setValue( value == null ? null : value.toLocalDate( ) );
return dp;
}
private TimePicker createTimePicker( String label, String width, boolean removeMargin, LocalTime value, long... durationOpt ){
TimePicker tp = new TimePicker( label );
tp.setRequired( true );
tp.setRequiredIndicatorVisible( true );
if( width != null ) tp.setWidth( width );
if( removeMargin ) tp.getStyle( ).set( "margin", "0px" );
if( value != null ) tp.setValue( value );
tp.setStep( Duration.ofMinutes( durationOpt.length == 0 ? 15 : durationOpt[ 0 ] ) );
return tp;
}
// manipulation methods
public DatePicker getDatePicker( ){
return datePicker;
}
public TimePicker getTimePicker( ){
return timePicker;
}
@Override
protected ZonedDateTime generateModelValue( ){
LocalDateTime ldt = getValueLDT( );
return ldt == null ? null : ldt.atZone( ZoneId.systemDefault( ) );
}
public LocalDateTime getValueLDT( ){
LocalDate ld = datePicker.getValue( );
LocalTime lt = timePicker.getValue( );
if( ld == null || lt == null ) return null;
return LocalDateTime.of( ld, lt );
}
@Override
public ZonedDateTime getValue( ){
return generateModelValue( );
}
@Override
protected void setPresentationValue( ZonedDateTime value ){
datePicker.setValue( value == null ? null : value.toLocalDate( ) );
if( value != null ) timePicker.setValue( value.toLocalTime( ) );
}
}
`
`public class ProductActivityDto implements java.io.Serializable {
private Integer idProductActivity;
private ZonedDateTime registerDate;
public ProductActivityDto( ) {
registerDate = ZonedDateTime.now( );
}
public Integer getIdProductActivity( ){
return idProductActivity;
}
public void setIdProductActivity( Integer idProductActivity ){
this.idProductActivity = idProductActivity;
}
public ZonedDateTime getRegisterDate( ){
return registerDate;
}
public void setRegisterDate( ZonedDateTime registerDate ){
this.registerDate = registerDate;
}
} `
The code was so simple, and I think you could reproduce it with my first comment by yourself :) I can not reproduce all bugs I come across, because I have to work for my company :)
Have a nice workday ...
@Legioth @ZheSun88
Vaadin 14.2.0 includes a DateTimePicker as an official component: https://github.com/vaadin/vaadin-date-time-picker-flow
There are some challenges, related to validation in particular, that are covered by the new component. Please consider using DateTimePicker instead of a custom implementation.
I created a simple DateTime Field with CustomField.
When I change the DatePicker -> Binder updates the DTO well for both Date and Time value.
When I change the TimePicker -> Binder does not update the DTO because of does not fire any change event for CustomField or Binder.