Dialogs: HTML form enhancements (#4172)

* Dialogs: HTML form enhancements

In preparation for https://github.com/abapGit/abapGit/issues/4171, HTML forms were enhanced as follows:

- New integer fields (type "number") with min/max, https://github.com/abapGit/abapGit/issues/3559
- Added support for minlength/maxlength for text fields
- Added support for read-only fields
- Added support for password fields
- New option for adding a help button to the form (with URL link)
- Moved HTML snippets to render method
- Changed parameters to csequence to also accept char variables (like abap_true)
- Minor adjustments to styles

* Lint and fix ul/fieldgroup

* Min/max validation, textarea

* Close textarea tag

Co-authored-by: Lars Hvam <larshp@hotmail.com>
This commit is contained in:
Marc Bernard 2020-11-14 05:28:19 -05:00 committed by GitHub
parent 61599d8225
commit 16e8f3d02d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 264 additions and 83 deletions

View File

@ -1099,6 +1099,11 @@ settings_tab tr:first-child td { border-top: 0px; }
box-sizing: border-box;
height: 2.5em;
}
.dialog input[type="number"] {
width: 25%;
box-sizing: border-box;
height: 2.5em;
}
.dialog .radio-container input[type="radio"] {
visibility: hidden;
display: none;
@ -1130,6 +1135,9 @@ settings_tab tr:first-child td { border-top: 0px; }
.dialog fieldset {
margin-top: 1em;
border: 1px solid;
border-right: none;
border-left: none;
border-bottom: none;
border-radius: 6px; /* doesn't work in IE ? */
padding-bottom: 1em;
}
@ -1137,8 +1145,11 @@ settings_tab tr:first-child td { border-top: 0px; }
margin-top: 0;
}
.dialog fieldset legend {
font-size: small;
text-transform: uppercase;
font-size: large;
font-style: bold;
padding-left: 0.5em;
padding-right: 0.5em;
}
.dialog .dialog-help {
float: left;
}

View File

@ -497,6 +497,7 @@ table.settings_tab input:focus {
.dialog li.error small {
color: #ff5959;
}
.dialog li.error input[type="number"],
.dialog li.error input[type="text"] {
border-color: #ff5959;
}
@ -519,5 +520,14 @@ table.settings_tab input:focus {
border-color: #dfdfdf;
}
.dialog fieldset legend {
color: #ccc;
color: #444;
}
.dialog input:read-only {
background-color: #f4f4f4;
color: var(--theme-greyscale-dark);
}
/* for IE */
.dialog input[readonly] {
background-color: #f4f4f4;
color: var(--theme-greyscale-dark);
}

View File

@ -7,61 +7,88 @@ CLASS zcl_abapgit_html_form DEFINITION
CLASS-METHODS create
IMPORTING
!iv_form_id TYPE string OPTIONAL
!iv_form_id TYPE csequence OPTIONAL
!iv_help_page TYPE csequence OPTIONAL
RETURNING
VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form.
METHODS render
IMPORTING
!iv_form_class TYPE string
!iv_form_class TYPE csequence
!io_values TYPE REF TO zcl_abapgit_string_map
!io_validation_log TYPE REF TO zcl_abapgit_string_map OPTIONAL
RETURNING
VALUE(ri_html) TYPE REF TO zif_abapgit_html.
METHODS command
IMPORTING
!iv_label TYPE string
!iv_action TYPE string
!iv_label TYPE csequence
!iv_action TYPE csequence
!iv_is_main TYPE abap_bool DEFAULT abap_false
!iv_as_a TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form.
METHODS text
IMPORTING
!iv_label TYPE string
!iv_name TYPE string
!iv_hint TYPE string OPTIONAL
!iv_label TYPE csequence
!iv_name TYPE csequence
!iv_hint TYPE csequence OPTIONAL
!iv_required TYPE abap_bool DEFAULT abap_false
!iv_upper_case TYPE abap_bool DEFAULT abap_false
!iv_placeholder TYPE string OPTIONAL
!iv_side_action TYPE string OPTIONAL
!iv_readonly TYPE abap_bool DEFAULT abap_false
!iv_password TYPE abap_bool DEFAULT abap_false
!iv_placeholder TYPE csequence OPTIONAL
!iv_side_action TYPE csequence OPTIONAL
!iv_min TYPE i DEFAULT cl_abap_math=>min_int4
!iv_max TYPE i DEFAULT cl_abap_math=>max_int4
RETURNING
VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form.
METHODS textarea
IMPORTING
!iv_label TYPE csequence
!iv_name TYPE csequence
!iv_rows TYPE i DEFAULT 3
!iv_hint TYPE csequence OPTIONAL
!iv_required TYPE abap_bool DEFAULT abap_false
!iv_readonly TYPE abap_bool DEFAULT abap_false
!iv_placeholder TYPE csequence OPTIONAL
RETURNING
VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form.
METHODS number
IMPORTING
!iv_label TYPE csequence
!iv_name TYPE csequence
!iv_hint TYPE csequence OPTIONAL
!iv_required TYPE abap_bool DEFAULT abap_false
!iv_readonly TYPE abap_bool DEFAULT abap_false
!iv_min TYPE i DEFAULT cl_abap_math=>min_int4
!iv_max TYPE i DEFAULT cl_abap_math=>max_int4
RETURNING
VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form.
METHODS checkbox
IMPORTING
!iv_label TYPE string
!iv_name TYPE string
!iv_hint TYPE string OPTIONAL
!iv_label TYPE csequence
!iv_name TYPE csequence
!iv_hint TYPE csequence OPTIONAL
RETURNING
VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form.
METHODS radio
IMPORTING
!iv_label TYPE string
!iv_name TYPE string
!iv_default_value TYPE string OPTIONAL
!iv_hint TYPE string OPTIONAL
!iv_label TYPE csequence
!iv_name TYPE csequence
!iv_default_value TYPE csequence OPTIONAL
!iv_hint TYPE csequence OPTIONAL
RETURNING
VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form.
METHODS option
IMPORTING
!iv_label TYPE string
!iv_value TYPE string
!iv_label TYPE csequence
!iv_value TYPE csequence
RETURNING
VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form.
METHODS start_group
IMPORTING
!iv_label TYPE string
!iv_name TYPE string
!iv_hint TYPE string OPTIONAL
!iv_label TYPE csequence
!iv_name TYPE csequence
!iv_hint TYPE csequence OPTIONAL
RETURNING
VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form.
METHODS normalize_form_data
@ -103,6 +130,11 @@ CLASS zcl_abapgit_html_form DEFINITION
default_value TYPE string,
side_action TYPE string,
subitems TYPE ty_subitems,
readonly TYPE abap_bool,
password TYPE abap_bool,
min TYPE i,
max TYPE i,
rows TYPE i,
* onclick ???
END OF ty_field.
TYPES:
@ -120,6 +152,8 @@ CLASS zcl_abapgit_html_form DEFINITION
radio TYPE i VALUE 2,
checkbox TYPE i VALUE 3,
field_group TYPE i VALUE 4,
number TYPE i VALUE 5,
textarea TYPE i VALUE 6,
END OF c_field_type.
DATA:
mt_fields TYPE STANDARD TABLE OF ty_field
@ -127,6 +161,7 @@ CLASS zcl_abapgit_html_form DEFINITION
DATA:
mt_commands TYPE STANDARD TABLE OF ty_command.
DATA mv_form_id TYPE string.
DATA mv_help_page TYPE string.
METHODS render_field
IMPORTING
@ -142,7 +177,7 @@ ENDCLASS.
CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
CLASS zcl_abapgit_html_form IMPLEMENTATION.
METHOD checkbox.
@ -152,10 +187,7 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ls_field-type = c_field_type-checkbox.
ls_field-name = iv_name.
ls_field-label = iv_label.
IF iv_hint IS NOT INITIAL.
ls_field-hint = | title="{ iv_hint }"|.
ENDIF.
ls_field-hint = iv_hint.
APPEND ls_field TO mt_fields.
@ -188,6 +220,7 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
CREATE OBJECT ro_form.
ro_form->mv_form_id = iv_form_id.
ro_form->mv_help_page = iv_help_page.
IF ro_form->mv_form_id IS INITIAL.
GET TIME STAMP FIELD lv_ts.
@ -216,6 +249,13 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ro_form_data->set(
iv_key = <ls_field>-name
iv_val = to_upper( lv_value ) ).
ELSEIF <ls_field>-type = c_field_type-number.
IF lv_value NA '0123456789- '.
ENDIF.
ro_form_data->set(
iv_key = <ls_field>-name
iv_val = lv_value ).
ELSE.
ro_form_data->set(
iv_key = <ls_field>-name
@ -227,6 +267,26 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ENDMETHOD.
METHOD number.
DATA ls_field LIKE LINE OF mt_fields.
ls_field-type = c_field_type-number.
ls_field-name = iv_name.
ls_field-label = iv_label.
ls_field-readonly = iv_readonly.
ls_field-min = iv_min.
ls_field-max = iv_max.
ls_field-hint = iv_hint.
ls_field-required = iv_required.
APPEND ls_field TO mt_fields.
ro_self = me.
ENDMETHOD.
METHOD option.
FIELD-SYMBOLS <ls_last> LIKE LINE OF mt_fields.
@ -258,10 +318,7 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ls_field-name = iv_name.
ls_field-label = iv_label.
ls_field-default_value = iv_default_value.
IF iv_hint IS NOT INITIAL.
ls_field-hint = | title="{ iv_hint }"|.
ENDIF.
ls_field-hint = iv_hint.
APPEND ls_field TO mt_fields.
@ -274,6 +331,7 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
FIELD-SYMBOLS <ls_field> LIKE LINE OF mt_fields.
FIELD-SYMBOLS <ls_cmd> LIKE LINE OF mt_commands.
DATA lv_hint TYPE string.
DATA ls_form_id TYPE string.
DATA lv_cur_group TYPE string.
@ -293,17 +351,27 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
EXIT.
ENDLOOP.
ri_html->add( |<ul>| ).
LOOP AT mt_fields ASSIGNING <ls_field>.
AT FIRST.
IF <ls_field>-type <> c_field_type-field_group.
ri_html->add( |<ul>| ).
ENDIF.
ENDAT.
IF <ls_field>-type = c_field_type-field_group.
IF lv_cur_group IS NOT INITIAL AND lv_cur_group <> <ls_field>-name.
ri_html->add( '</fieldset>' ).
ri_html->add( |</ul>| ).
ri_html->add( |</fieldset>| ).
ENDIF.
IF <ls_field>-hint IS NOT INITIAL.
lv_hint = | title="{ <ls_field>-hint }"|.
ELSE.
lv_hint = ''.
ENDIF.
lv_cur_group = <ls_field>-name.
ri_html->add( |<fieldset name="{ <ls_field>-name }">| ).
ri_html->add( |<legend{ <ls_field>-hint }>{ <ls_field>-label }</legend>| ).
ri_html->add( |<legend{ lv_hint }>{ <ls_field>-label }</legend>| ).
ri_html->add( |<ul>| ).
CONTINUE.
ENDIF.
@ -314,14 +382,25 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
is_field = <ls_field> ).
AT LAST.
ri_html->add( |</ul>| ).
IF lv_cur_group IS NOT INITIAL.
ri_html->add( '</fieldset>' ).
ri_html->add( |</fieldset>| ).
ENDIF.
ENDAT.
ENDLOOP.
ri_html->add( |<ul>| ).
ri_html->add( |<li class="dialog-commands">| ).
IF mv_help_page IS NOT INITIAL.
ri_html->add_a(
iv_txt = zcl_abapgit_gui_buttons=>help( )
iv_typ = zif_abapgit_html=>c_action_type-url
iv_act = mv_help_page
iv_class = 'dialog-help'
iv_title = 'Help' ).
ENDIF.
LOOP AT mt_commands ASSIGNING <ls_cmd>.
render_command(
ii_html = ri_html
@ -329,7 +408,6 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ENDLOOP.
ri_html->add( |</li>| ).
ri_html->add( |</ul>| ).
ri_html->add( |</form>| ).
ri_html->add( |</div>| ).
@ -366,6 +444,10 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
DATA lv_value TYPE string.
DATA lv_checked TYPE string.
DATA lv_item_class TYPE string.
DATA lv_hint TYPE string.
DATA lv_required TYPE string.
DATA lv_attr TYPE string.
DATA lv_type TYPE string.
FIELD-SYMBOLS <ls_opt> LIKE LINE OF is_field-subitems.
" Get value and validation error from maps
@ -383,14 +465,29 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
lv_item_class = | class="{ lv_item_class }"|.
ENDIF.
IF is_field-required = abap_true.
lv_required = ' <em>*</em>'.
ENDIF.
IF is_field-hint IS NOT INITIAL.
lv_hint = | title="{ is_field-hint }"|.
ENDIF.
IF is_field-readonly = abap_true.
lv_attr = lv_attr && ' readonly'.
ENDIF.
IF is_field-placeholder IS NOT INITIAL.
lv_attr = lv_attr && | placeholder="{ is_field-placeholder }"|.
ENDIF.
" Render field
ii_html->add( |<li{ lv_item_class }>| ).
CASE is_field-type.
WHEN c_field_type-text.
WHEN c_field_type-text OR c_field_type-number.
ii_html->add( |<label for="{ is_field-name }"{ is_field-hint }>{
is_field-label }{ is_field-required }</label>| ).
ii_html->add( |<label for="{ is_field-name }"{ lv_hint }>{ is_field-label }{ lv_required }</label>| ).
IF lv_error IS NOT INITIAL.
ii_html->add( |<small>{ lv_error }</small>| ).
ENDIF.
@ -399,8 +496,16 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ii_html->add( '<div class="input-container">' ). " Ugly :(
ENDIF.
ii_html->add( |<input type="text" name="{ is_field-name }" id="{
is_field-name }"{ is_field-placeholder } value="{ lv_value }"{ is_field-dblclick }>| ).
IF is_field-type = c_field_type-number.
lv_type = 'number'.
ELSEIF is_field-password = abap_true.
lv_type = 'password'.
ELSE.
lv_type = 'text'.
ENDIF.
ii_html->add( |<input type="{ lv_type }" name="{ is_field-name }" id="{
is_field-name }" value="{ lv_value }"{ is_field-dblclick }{ lv_attr }>| ).
IF is_field-side_action IS NOT INITIAL.
ii_html->add( '</div>' ).
@ -409,6 +514,17 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ii_html->add( '</div>' ).
ENDIF.
WHEN c_field_type-textarea.
ii_html->add( |<label for="{ is_field-name }"{ lv_hint }>{ is_field-label }{ lv_required }</label>| ).
IF lv_error IS NOT INITIAL.
ii_html->add( |<small>{ lv_error }</small>| ).
ENDIF.
ii_html->add( |<textarea name="{ is_field-name }" id="{
is_field-name }" value="{ lv_value }" rows="{ is_field-rows }"{ lv_attr }>| ).
ii_html->add( |</textarea>| ).
WHEN c_field_type-checkbox.
IF lv_error IS NOT INITIAL.
@ -418,12 +534,11 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
lv_checked = ' checked'.
ENDIF.
ii_html->add( |<input type="checkbox" name="{ is_field-name }" id="{ is_field-name }"{ lv_checked }>| ).
ii_html->add( |<label for="{ is_field-name }"{ is_field-hint }>{
is_field-label }{ is_field-required }</label>| ).
ii_html->add( |<label for="{ is_field-name }"{ lv_hint }>{ is_field-label }</label>| ).
WHEN c_field_type-radio.
ii_html->add( |<label{ is_field-hint }>{ is_field-label }{ is_field-required }</label>| ).
ii_html->add( |<label{ lv_hint }>{ is_field-label }</label>| ).
IF lv_error IS NOT INITIAL.
ii_html->add( |<small>{ lv_error }</small>| ).
ENDIF.
@ -458,10 +573,7 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ls_field-type = c_field_type-field_group.
ls_field-label = iv_label.
ls_field-name = iv_name.
IF iv_hint IS NOT INITIAL.
ls_field-hint = | title="{ iv_hint }"|.
ENDIF.
ls_field-hint = iv_hint.
APPEND ls_field TO mt_fields.
@ -478,10 +590,13 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
ls_field-name = iv_name.
ls_field-label = iv_label.
ls_field-upper_case = iv_upper_case.
IF iv_hint IS NOT INITIAL.
ls_field-hint = | title="{ iv_hint }"|.
ENDIF.
ls_field-readonly = iv_readonly.
ls_field-min = iv_min.
ls_field-max = iv_max.
ls_field-password = iv_password.
ls_field-hint = iv_hint.
ls_field-required = iv_required.
ls_field-placeholder = iv_placeholder.
IF iv_side_action IS NOT INITIAL AND mv_form_id IS NOT INITIAL.
ls_field-item_class = 'with-command'.
@ -492,13 +607,25 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
}').submit()"|.
ENDIF.
IF iv_required = abap_true.
ls_field-required = ' <em>*</em>'.
ENDIF.
APPEND ls_field TO mt_fields.
IF iv_placeholder IS NOT INITIAL.
ls_field-placeholder = | placeholder="{ iv_placeholder }"|.
ENDIF.
ro_self = me.
ENDMETHOD.
METHOD textarea.
DATA ls_field LIKE LINE OF mt_fields.
ls_field-type = c_field_type-textarea.
ls_field-name = iv_name.
ls_field-label = iv_label.
ls_field-readonly = iv_readonly.
ls_field-hint = iv_hint.
ls_field-required = iv_required.
ls_field-placeholder = iv_placeholder.
ls_field-rows = iv_rows.
APPEND ls_field TO mt_fields.
@ -510,6 +637,7 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
METHOD validate_required_fields.
DATA lv_value TYPE string.
DATA lv_number TYPE i.
FIELD-SYMBOLS <ls_field> LIKE LINE OF mt_fields.
CREATE OBJECT ro_validation_log.
@ -521,6 +649,38 @@ CLASS ZCL_ABAPGIT_HTML_FORM IMPLEMENTATION.
iv_key = <ls_field>-name
iv_val = |{ <ls_field>-label } cannot be empty| ).
ENDIF.
CASE <ls_field>-type.
WHEN c_field_type-text.
IF <ls_field>-min <> cl_abap_math=>min_int4 AND strlen( lv_value ) < <ls_field>-min.
ro_validation_log->set(
iv_key = <ls_field>-name
iv_val = |{ <ls_field>-label } must not be shorter than { <ls_field>-min } characters| ).
ENDIF.
IF <ls_field>-max <> cl_abap_math=>max_int4 AND strlen( lv_value ) > <ls_field>-max.
ro_validation_log->set(
iv_key = <ls_field>-name
iv_val = |{ <ls_field>-label } must not be longer than { <ls_field>-max } characters| ).
ENDIF.
WHEN c_field_type-number.
TRY.
lv_number = lv_value.
CATCH cx_root.
ro_validation_log->set(
iv_key = <ls_field>-name
iv_val = |{ <ls_field>-label } is not a number| ).
CONTINUE.
ENDTRY.
IF <ls_field>-min <> cl_abap_math=>min_int4 AND lv_number < <ls_field>-min.
ro_validation_log->set(
iv_key = <ls_field>-name
iv_val = |{ <ls_field>-label } must not be lower than { <ls_field>-min }| ).
ENDIF.
IF <ls_field>-max <> cl_abap_math=>max_int4 AND lv_number > <ls_field>-max.
ro_validation_log->set(
iv_key = <ls_field>-name
iv_val = |{ <ls_field>-label } must not be higher than { <ls_field>-max }| ).
ENDIF.
ENDCASE.
ENDLOOP.
ENDMETHOD.

View File

@ -5,7 +5,7 @@
<VSEOCLASS>
<CLSNAME>ZCL_ABAPGIT_HTML_FORM</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abapgit html form component</DESCRIPT>
<DESCRIPT>abapgit - HTML form component</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>