Skip to Content
Personal Insights

Random collection of useful code fragments for CAP Fiori Elements and SAPUI5

This blog post is dedicated to being a random collection of useful code fragments you might want to use. As any of these weren’t easy to find in documentation or code samples, my intention is to share some code fragments including a description, so whenever you google something, and you don’t see any answered question on SAP Community or StackOverflow, you land here 🙂

This may result in a series of random collections, but this one is mainly focussing on SAPUI5 and Fiori Elements for CAP. Potential backend code is written in NodeJS. Be aware that some solutions may not use best practices or could be potentially already replaced by a cleaner solution. However, the code fragments shall be still working. You may see other code fragments of other solutions included or used.

 

SAPUI5 masked IBAN field including validation

Although IBAN validation may sound simple, it is more complicated as you’d expect. You might know that IBANs don’t have a fixed length, they have country-depending lengths. Furthermore, they also can include characters.

Despite that the SAPUI5 MaskInput is only designed to receive a string of arbitrary length, it can be still used given the maximum size an IBAN can be.

The code fragment for the view looks as follows:

<MaskInput id="iBankAccountIBAN" change="validateIBAN" fieldGroupIds="RegForm" value="{path: 'BankAccountIBAN', type: 'sap.ui.model.type.String'}" mask="LLNN XXXX XXXX XXXX XXXX XXXX XXXX XXXX"
													placeholderSymbol=" " placeholder="" required="true">
	<rules>
		<MaskInputRule maskFormatSymbol="L" regex="[A-Za-z]"/>
		<MaskInputRule maskFormatSymbol="N" regex="[0-9]"/>
		<MaskInputRule maskFormatSymbol="X" regex="[A-Za-z0-9]"/>
	</rules>
</MaskInput>

The matching validation logic in the controller looks as follows:

validateIBAN: function (oEvent) {
    var value = oEvent.getParameter("value");
    this.markFieldError(oEvent.getSource(), !this._isValidIBANNumber(value) ? this.oBundle.getText("noValidIBAN") : "");
},

_isValidIBANNumber: function (sValue) {
    var oIBANLanguageLengths = {
        AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22, BR: 29,
        CH: 21, CR: 21, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28, EE: 20, ES: 24,
        FI: 18, FO: 18, FR: 27, GB: 22, GI: 23, GL: 18, GR: 27, GT: 28, HR: 21,
        HU: 28, IE: 22, IL: 23, IS: 26, IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28,
        LI: 21, LT: 20, LU: 20, LV: 21, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27,
        MT: 31, MU: 30, NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29,
        RO: 24, RS: 22, SA: 24, SE: 24, SI: 19, SK: 24, SM: 27, TN: 24, TR: 26
    };
    var iban = String(sValue).toUpperCase().replace(/[^A-Z0-9]/g, ''), // keep only alphanumeric characters
        code = iban.match(/^([A-Z]{2})(\d{2})([A-Z\d]+)$/), // match and capture (1) the country code, (2) the check digits, and (3) the rest
        digits;
    // check syntax and length
    if (!code || iban.length !== oIBANLanguageLengths[code[1]]) {
        return false;
    }
    // rearrange country code and check digits, and convert chars to ints
    digits = (code[3] + code[1] + code[2]).replace(/[A-Z]/g, function (letter) {
        return letter.charCodeAt(0) - 55;
    });
    // final check
    return this._mod97(digits) === 1;
},
_mod97: function (sIBANFragment) {
    var checksum = sIBANFragment.slice(0, 2), fragment;
    for (var offset = 2; offset < sIBANFragment.length; offset += 7) {
        fragment = String(checksum) + sIBANFragment.substring(offset, offset + 7);
        checksum = parseInt(fragment, 10) % 97;
    }
    return checksum;
},

markFieldError: function (oControl, sError) {
    if (oControl !== undefined) {
        if (sError) {
            oControl.setValueStateText(sError);
            oControl.setValueState("Error");
        } else {
            oControl.setValueState("None");
        }
    }
},

 

Complex if/elseif/else constructs in CAP Service Annotation

Whenever you have a complex construct in a CAP service, you can always go back and use standard (HANA)SQL code to implement this logic. Be aware that CAP CDL still requires you to define the type of column you add.

entity BP as
    select from my.BP {
        *,
        (
            case
                when
                    BPSalutation = '01'
                then
                    'Herr ' || BPFirstName || ' ' || BPSurName
                when
                    BPSalutation = '02'
                then
                    'Frau ' || BPFirstName || ' ' || BPSurName
                when
                    BPSalutation = '03'
                then
                    'Firma ' || BPSurName
                else
                    ' '
            end
        )   as BPFullName : String,
        
        BPStreet || ' ' || BPHouseNumber  as BPAddress        : String,
        BPZip || ' ' || BPCity            as BPCityFull       : String
};

 

Fiori Elements Facet Hiding

In Fiori Elements, you can use UI.Hidden to dynamically show or hide a facet based on a value. The following example shows you a service annotation, where the logic is implemented and the Fiori Elements CDS annotation.

entity Table @readonly as
    select from my.Table {
      *,
 
      // unequals because boolean is about hiding or not
      (
        case
          when
            TableColumnOne != false and TableColumnCountry = 'LI'
          then
            true
          else
            false
        end
      ) as CountrySpecific    : Boolean, 
}
Facets               : [
    ...
    {
        $Type  : 'UI.ReferenceFacet',
        Label  : 'Landesspezifische Information',
        Target : '@UI.FieldGroup#CountryDetails',
        ![@UI.Hidden]: CountrySpecific
    }
    ...
]

 

Fiori Elements String Concat

A string concat is pretty difficult in CAP CDS Fiori Elements annotations. As many help documents are referring to ABAP CDS or an XML Annotation, here is the following example done in CAP CDS Fiori Elements:

HeaderInfo           : {
    ...
    Description    : {
        Value      : { 
            ![$edmJson]: { 
                ![$Function]: 'odata.concat',
                ![$Apply]: [ 
                    'Veranschlagte Summe: ',
                        { ![$Path] : 'SalesProposition' },
                    ' CHF'
                ]
            }
        }
    }
},

 

I hope you enjoy this random collection of code. Maybe there will be soon part 2 🙂

Be the first to leave a comment
You must be Logged on to comment or reply to a post.