Overview
To check user input, the S10 framework offers special "validate" methods that are automatically processed after input. Both individual values and combinations of values can be checked with this. Incorrect entries are marked in the HTML mask and the input focus is set to the first incorrect field.

In general, input errors can be reduced by offering the input values in the form of drop-down lists or by calling them up as input help. The S10 Framework offers special support for both techniques. However, there often remain fields where direct input should be possible, and there may also be checks that include some values of a drop-down list in conjunction with other input values.

Implementation
Input validation should preferably be done in validate methods, because only then is the validation done automatically and incorrect fields are marked. A validate method is a public method of the object (not a class method) whose import parameters are identical to attribute names. Supported are atomic attributes, but not object references and tables. The method name begins with "validate_" and is otherwise freely selectable. The import parameters can optionally be passed as a value with value(...), which makes no difference to the validation. Syntactically, it is then allowed to change the passed value in the method, which is sometimes convenient but less recommended; the class attribute itself does not change because of the value passing. 

The S10 framework first performs all single field checks (only one import parameter), then the combination of two fields, then three fields and so on. In case of an error message in a validate method by s10errormessage(), the check is aborted, the error message is displayed and the fields are marked. In each case, the order of the input values to be checked is determined by their position in the HTML file, i.e. usually also in the display from top to bottom and from left to right.

If the value of an input parameter is inital and the interface parameter is not marked as optional the validate method is not called.

You can also implement several validate methods for a single field or a combination of input fields, which are then called one after the other. The order of the call for several validate methods for the same attribute or the same attribute combination is alphabetical by method name.

If a validate method was successful, i.e. did not lead to an error message, it will not be executed again the next time as long as the import parameters have kept the same value. It is therefore important to list all attributes on which the method depends in the import parameters of the method. If this is not possible, e.g. because all rows of an input table are checked, the validate method is unsuitable and one should call one's own general check method at "Enter", "Check" or at the latest at "Save".

Example
In an ABAP class we have defined the following eight attributes:

ABAP

data:
      kunnr type vbak-kunnr, " customer number
      vkorg type vbak-vkorg, " sales organization
      vtweg type vbak-vtweg, " distribution channel
      spart type vbak-spart, " division
      auart type vbak-auart, " order type
      date1 type vbak-audat, " order date (from)
      date2 type vbak-audat, " order date (to) 
      matnr type vbap-matnr. " material number

In the input mask, all fields except "date1", "date2" and "matnr" are mandatory inputs, which is indicated by "required" in the <input> tag. The S10 framework gives the assigned label a red asterisk * as an identifier: 

HTML
<!-- customer number -->
<div class="infoblock" style="width:240px; height:50px;">
    <label class="label output" name="kunnr"
           for="kunnr"></label><br>
    <input class="input" name="kunnr" id="kunnr"
           style="width:200px;" required>
</div> <br />

<!-- sales organization -->
<div class="infoblock" style="width:240px; height:50px;">
    <label class="label output" name="vkorg"
           for="vkorg"></label><br>
    <select class='inputselect' size="1" name='vkorg'
            id="vkorg" style='width: 100%;' required
            data-s10dropdownlist='vkorg@dropdownlist'>
    </select>
</div><br />

<!-- distribution channel -->
<div class="infoblock" style="width:240px; height:50px;">
    <label class="label output" name="vtweg"
           for="vtweg"></label><br>
    <select class='inputselect' size="1" name='vtweg'
            id="vtweg" style='width: 100%;' required
            data-s10dropdownlist='vtweg@dropdownlist'>
    </select>
</div><br />

<!-- division -->
<div class="infoblock" style="width:240px; height:50px;">
    <label class="label output" name="spart"
           for="spart"></label><br>
    <select class='inputselect' size="1" name='spart'
            id="spart" style='width: 100%;' required
            data-s10dropdownlist='spart@dropdownlist'>
    </select>
</div><br />

<!-- order type -->
<div class="infoblock" style="width:240px; height:50px;">
    <label class="label output" name="auart"
           for="auart"></label><br>
    <input class="input" name="auart" id="auart"
           style="width:100px" required>
</div><br />

<!-- material number -->
<div class="infoblock" style="width:240px; height:50px;">
    <label class="label output" name="matnr"
           for="matnr"></label><br>
    <input class="input" name="matnr" id="matnr">
</div><br />

<!-- date1 -->
<div class="infoblock" style="width:240px; height:50px;">
    <label class="label output" name="date1"
           for="date1"></label>
    <label class="label">von</label><br>
    <input type="date" class="input" name="date1"
           id="date1">
</div>

<!-- date 2 -->
<div class="infoblock" style="width:240px; height:50px;">
    <label class="label output" name="date2"
           for="date2"></label>
    <label class="label">bis</label><br>
    <input type="date" class="input" name="date2"
           id="date2">
</div>

In this form, without having defined our own test routines, the following is already active:

  • Mandatory inputs are checked




  • Maximum input lengths are checked according to the SAP Data Dictionary




  • Date fields with <input type="date">

 

We now implement the following individual checks:

  • Valid customer number
  • Customer not marked for deletion
  • Valid material number

ABAP

* validation method declaration, single attributes
methods:
      validate_kunnr
        importing
          kunnr type vbak-kunnr,

      validate_kunnr_del
        importing
          kunnr type vbak-kunnr,

      validate_matnr
        importing
          matnr type vbap-matnr. 
* validation method implementation, single attributes
   method validate_kunnr.
    data: tempkunnr type kna1-kunnr.
    select single kunnr into tempkunnr from kna1 where kunnr = kunnr.
    if sy-subrc ne 0.
      s10errormessage(
          text = |CLient |
                 && s10getuservalue( 'kunnr' )
                 && | does not exist| ).

    endif.
  endmethod.

  method    validate_kunnr_del.
    data: tempnodel type kna1-nodel.
    select single nodel into tempnodel from kna1 where kunnr = kunnr.
    if tempnodel = 'X'.
      s10errormessage(
          text = |CLient |
                 && s10getuservalue( 'kunnr' )
                 && | marked for deletion| ).

    endif.
  endmethod.
  method     validate_matnr.
    data: tempmatnr type vbap-matnr.
    select single matnr into tempmatnr from mara where matnr = matnr.
    if sy-subrc ne 0.
      s10errormessage(
          text = |Material |
                 && s10getuservalue( 'matnr' )
                 && | does not exist| ).

    endif.
  endmethod.

Output of messages in case of incorrect input:

 

Next, we implement checks on attribute combinations:

  • If date interval is specified: "Date from" is less than or equal to "Date to "
  • Customer is created in the sales area concerned
  • Material is created in the sales area concerned
  • User has authorisation for sales area (authorisation V_VBAK_VKO )

ABAP

* validation method declaration, attribute combinations
methods:
      validate_dates
        importing
          date1 type vbak-audat
          date2 type vbak-audat,

      validate_salesarea_auth
        importing
          vkorg type vbak-vkorg
          vtweg type vbak-vtweg
          spart type vbak-spart,

      validate_kunnr_salesarea
        importing
          kunnr type vbak-kunnr
          vkorg type vbak-vkorg
          vtweg type vbak-vtweg
          spart type vbak-spart,

      validate_matnr_salesarea
        importing
          matnr type vbap-matnr
          vkorg type vbak-vkorg
          vtweg type vbak-vtweg
          spart type vbak-spart. 
* validation method implementation, attribute combinations
  method validate_dates.
    if date1 is not initial
    and date2 is not initial
    and date1 > date2.
      s10errormessage( text = | The start date is later than the end date| ).
    endif.
  endmethod.

  method validate_salesarea_auth.
    authority-check object 'V_VBAK_VKO'
      id 'VKORG' field vkorg
      id 'VTWEG' field vtweg
      id 'SPART' field spart
      id 'ACTVT' field '03'.
    if sy-subrc ne 0.
      s10errormessage(
        text = | No authorisation for the sales organization |
        && |(Authorization object V_VBAK_VKO)| ).
    endif.
  endmethod.

  method validate_kunnr_salesarea.

    data:
      vtwku     type tvkov-vtwku,
      spaku     type tvkos-spaku,
      tempkunnr type kna1-kunnr.

* read distribution channel for customer
    select single vtwku into vtwku from tvkov
        where vkorg = vkorg
        and vtweg = vtweg.
    if sy-subrc ne 0.
      vtwku = vtweg.
    endif.

* read division for customer
    select single spaku into spaku from tvkos
       where vkorg = vkorg
       and spart = spart.
    if sy-subrc ne 0.
      spaku = spart.
    endif.

* check existence in sales area
    select single kunnr into tempkunnr from knvv
      where kunnr = kunnr
      and   vkorg = vkorg
      and   vtweg = vtwku
      and   spart = spaku.

    if sy-subrc ne 0.
      s10errormessage(
          text = |Client |
                 && s10getuservalue( 'kunnr' )
                 && | not created in the sales organization| ).

    endif.
  endmethod.


  method  validate_matnr_salesarea.

* no validation if matnr is empty
    if matnr is initial.
      return.
    endif. 

    data:
      vtwku     type tvkov-vtwku,
      tempmatnr type vbap-matnr.

* read distribution channel for material
    select single vtwku into vtwku from tvkov
        where vkorg = vkorg
        and vtweg = vtweg.
    if sy-subrc ne 0.
      vtwku = vtweg.
    endif.

* check existence in sales area
    select single matnr into tempmatnr from mvke
      where matnr = matnr
      and   vkorg = vkorg
      and   vtweg = vtwku.

    if sy-subrc ne 0.
      s10setfocus( 'matnr' ). 
      s10errormessage(
          text = |Material |
                 && s10getuservalue( 'matnr' )
                 && | not created in the sales organization| ).

    endif.

  endmethod.

Output of messages in case of incorrect input:

 

 

 


WIth s10setfocus( 'matnr' ) before outputting the error message, we have set the input focus to the material number. The error message is then also displayed under this input field. 

Input checks in tables
Inputs in table cells can also be checked per line with validate methods. Again, these can be individual validations or a combination of entries within a line. The validate methods are created in the row object of the table.

In the following example, the error message is not displayed as a pop-up, but in a fixed message line. Details can be found in s10errormessage().

 

For the implementation, please note that the validate method is created in the row object of the table, in this case the order item "orderpos", and not in the class "order", in which the table of order items is defined.

ABAP

* class order
class order definition inheriting from /s10/any.

...

* order items
      orderitems type table of ref to orderpos. 

* class order item
class orderpos definition inheriting from /s10/any. 

...
methods:
   validate_material
        importing
          value(material) type matnr. 


...
 method validate_material.

* material exists?
    select single matnr into material from mara where matnr = material.
    if sy-subrc ne 0.
      s10errormessage( s10localize( 'ERROR_MATERIAL_INVALID' ) ).
    endif.

    vkorg = config=>parameter( 'vkorg' ).
    vtweg = config=>parameter( 'vtweg' ).

    select single matnr from mvke
        into material
          where matnr = material
          and   vkorg = vkorg
          and   vtweg = vtweg.

    if sy-subrc ne 0.
      s10errormessage( s10localize( 'ERROR_MATERIAL_VKORG_INVALID' ) ).
    endif.

  endmethod.

Components: S10 Framework