RAP Value Helps : Aides à la saisie basées sur les annotations dans ABAP Cloud

Catégorie
RAP
Publié
Auteur
Johannes

Les Value Helps (aides à la saisie) sont un élément central de toute application Fiori. Elles permettent aux utilisateurs de sélectionner confortablement des valeurs dans des listes prédéfinies. Dans RAP, les Value Helps sont définies de manière déclarative via des annotations CDS - sans écrire une seule ligne de code UI.

Concept de base des Value Helps

Les Value Helps dans RAP sont basées sur l’annotation @Consumption.valueHelpDefinition. Celle-ci lie un champ à une entité CDS qui sert de liste de valeurs.

Value Help simple

La configuration minimale consiste en l’annotation sur le champ cible :

define view entity ZC_SalesOrder
as projection on ZI_SalesOrder
{
@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_Customer',
element: 'CustomerId"
}
}]
key SalesOrderId,
CustomerId,
CustomerName,
OrderDate
}

Cette configuration affiche automatiquement une aide à la saisie avec tous les clients de ZI_Customer lorsque l’utilisateur clique sur le champ CustomerId.

Structure de l’annotation

@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_ValueHelpEntity', -- Nom de l'entité CDS
element: 'KeyField' -- Champ clé (optionnel)
},
qualifier: 'MyValueHelp', -- Identifiant unique
label: 'Sélection client', -- Titre du dialogue
useForValidation: true, -- Activer la validation
additionalBinding: [{...}], -- Affectations de champs supplémentaires
distinctValues: true -- Uniquement des valeurs uniques
}]

Design de l’entité Value Help

L’entité servant de Value Help doit être optimisée pour cet usage :

@EndUserText.label: 'Value Help Clients"
@ObjectModel.resultSet.sizeCategory: #XS
@Search.searchable: true
define view entity ZI_CustomerVH
as select from zcustomer
{
@UI.hidden: true
key customer_id as CustomerId,
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.8
customer_name as CustomerName,
@Search.defaultSearchElement: true
city as City,
country as Country,
@UI.hidden: true
blocked as IsBlocked
}
where blocked = '"

Bonnes pratiques pour les entités Value Help

AspectRecommandation
Taille@ObjectModel.resultSet.sizeCategory: #XS pour petites listes
Recherche@Search.searchable pour Typeahead
FiltreClause WHERE pour les entrées invalides
ChampsN’exposer que les champs pertinents

Différence : Value Helps simples vs. complexes

Value Help simple

Affiche uniquement le champ clé et optionnellement un texte de description :

@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_StatusVH',
element: 'StatusCode"
}
}]
Status,

L’entité Value Help :

define view entity ZI_StatusVH
as select from zstatus
{
key status_code as StatusCode,
status_text as StatusText
}

Value Help complexe

Contient plusieurs colonnes, des filtres et des champs de retour supplémentaires :

@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_MaterialVH',
element: 'MaterialNumber"
},
additionalBinding: [{
element: 'MaterialDescription',
localElement: 'MaterialText',
usage: #RESULT
}, {
element: 'MaterialGroup',
localElement: 'MaterialGroup',
usage: #RESULT
}, {
element: 'BaseUnit',
localElement: 'Unit',
usage: #RESULT
}]
}]
MaterialNumber,
MaterialText,
MaterialGroup,
Unit,

Value Help avec conditions de filtre

Les filtres restreignent les valeurs affichées. Il existe deux types : les filtres statiques et dynamiques.

Filtre statique

Filtre la Value Help sur des valeurs fixes :

@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_ProductVH',
element: 'ProductId"
},
additionalBinding: [{
element: 'ProductType',
localConstant: 'FINISHED',
usage: #FILTER
}]
}]
ProductId,

Cette Value Help n’affiche que les produits avec ProductType = 'FINISHED'.

Filtre dynamique (dépendant d’autres champs)

Le filtre est basé sur la valeur d’un autre champ :

define view entity ZC_PurchaseOrder
as projection on ZI_PurchaseOrder
{
key PurchaseOrderId,
@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_VendorVH',
element: 'VendorId"
},
additionalBinding: [{
element: 'PurchasingOrg',
localElement: 'PurchasingOrg',
usage: #FILTER
}]
}]
VendorId,
VendorName,
@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_PurchOrgVH',
element: 'PurchasingOrg"
}
}]
PurchasingOrg
}

Ici, seuls les fournisseurs appartenant à l’organisation d’achat sélectionnée sont affichés.

Combiner plusieurs filtres

@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_PlantVH',
element: 'Plant"
},
additionalBinding: [{
element: 'CompanyCode',
localElement: 'CompanyCode',
usage: #FILTER
}, {
element: 'SalesOrg',
localElement: 'SalesOrg',
usage: #FILTER
}, {
element: 'IsActive',
localConstant: 'X',
usage: #FILTER
}]
}]
Plant,

Cascading Value Helps (Aides à la saisie dépendantes)

Les Cascading Value Helps sont interdépendantes - la sélection dans une Value Help influence les options dans une autre.

Exemple : Pays -> Région -> Ville

define view entity ZC_Address
as projection on ZI_Address
{
key AddressId,
-- 1er niveau : Pays
@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_CountryVH',
element: 'CountryCode"
},
additionalBinding: [{
element: 'CountryName',
localElement: 'CountryName',
usage: #RESULT
}]
}]
CountryCode,
CountryName,
-- 2ème niveau : Région (filtrée par pays)
@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_RegionVH',
element: 'RegionCode"
},
additionalBinding: [{
element: 'CountryCode',
localElement: 'CountryCode',
usage: #FILTER
}, {
element: 'RegionName',
localElement: 'RegionName',
usage: #RESULT
}]
}]
RegionCode,
RegionName,
-- 3ème niveau : Ville (filtrée par région)
@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_CityVH',
element: 'CityCode"
},
additionalBinding: [{
element: 'RegionCode',
localElement: 'RegionCode',
usage: #FILTER
}, {
element: 'CityName',
localElement: 'CityName',
usage: #RESULT
}]
}]
CityCode,
CityName
}

Entités Value Help pour Cascading

-- Pays
define view entity ZI_CountryVH
as select from zcountry
{
key country_code as CountryCode,
country_name as CountryName
}
-- Régions (avec clé étrangère sur le pays)
define view entity ZI_RegionVH
as select from zregion
{
key region_code as RegionCode,
region_name as RegionName,
country_code as CountryCode -- Critère de filtre
}
-- Villes (avec clé étrangère sur la région)
define view entity ZI_CityVH
as select from zcity
{
key city_code as CityCode,
city_name as CityName,
region_code as RegionCode -- Critère de filtre
}

Value Help avec champs de sortie supplémentaires

Les champs de sortie supplémentaires transfèrent automatiquement des valeurs de la Value Help vers d’autres champs de l’entité.

Exemple : Données article

define view entity ZC_SalesOrderItem
as projection on ZI_SalesOrderItem
{
key SalesOrderId,
key ItemNumber,
@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_MaterialVH',
element: 'MaterialNumber"
},
additionalBinding: [
-- Champs de retour
{ element: 'MaterialDescription', localElement: 'MaterialText', usage: #RESULT },
{ element: 'BaseUnit', localElement: 'Unit', usage: #RESULT },
{ element: 'MaterialGroup', localElement: 'MatGroup', usage: #RESULT },
{ element: 'GrossWeight', localElement: 'Weight', usage: #RESULT },
-- Aussi comme filtre
{ element: 'SalesOrg', localElement: 'SalesOrg', usage: #FILTER_AND_RESULT }
]
}]
MaterialNumber,
MaterialText,
Unit,
MatGroup,
Weight,
SalesOrg,
Quantity,
NetPrice
}

Options d’usage

ValeurDescription
#RESULTLa valeur est retournée
#FILTERLa valeur sert de filtre
#FILTER_AND_RESULTLes deux combinés

Exemple pratique : Client avec adresse

@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_CustomerVH',
element: 'CustomerId"
},
additionalBinding: [{
element: 'CustomerName',
localElement: 'CustomerName',
usage: #RESULT
}, {
element: 'Street',
localElement: 'CustomerStreet',
usage: #RESULT
}, {
element: 'City',
localElement: 'CustomerCity',
usage: #RESULT
}, {
element: 'PostalCode',
localElement: 'CustomerPostalCode',
usage: #RESULT
}, {
element: 'Country',
localElement: 'CustomerCountry',
usage: #RESULT
}, {
element: 'PaymentTerms',
localElement: 'PaymentTerms',
usage: #RESULT
}]
}]
CustomerId,
CustomerName,
CustomerStreet,
CustomerCity,
CustomerPostalCode,
CustomerCountry,
PaymentTerms,

Plusieurs Value Helps pour un champ

Un champ peut avoir plusieurs Value Helps alternatives :

@Consumption.valueHelpDefinition: [
{
entity: { name: 'ZI_CustomerVH', element: 'CustomerId' },
qualifier: 'AllCustomers',
label: 'Tous les clients"
},
{
entity: { name: 'ZI_KeyAccountVH', element: 'CustomerId' },
qualifier: 'KeyAccounts',
label: 'Clients clés',
additionalBinding: [{
element: 'IsKeyAccount',
localConstant: 'X',
usage: #FILTER
}]
},
{
entity: { name: 'ZI_RecentCustomerVH', element: 'CustomerId' },
qualifier: 'RecentCustomers',
label: 'Utilisés récemment"
}
]
CustomerId,

L’utilisateur peut choisir entre les Value Helps.

Validation avec Value Helps

L’annotation useForValidation vérifie les valeurs saisies par rapport à la Value Help :

@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_CurrencyVH',
element: 'CurrencyCode"
},
useForValidation: true
}]
Currency,

Pour les saisies invalides, Fiori affiche automatiquement un message d’erreur.

Validation dans la Behavior Definition

En plus de la validation UI, la validation côté backend devrait également être effectuée :

validation validateCurrency on save { field Currency; }
METHOD validateCurrency.
READ ENTITIES OF zi_salesorder IN LOCAL MODE
ENTITY SalesOrder
FIELDS ( Currency )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_orders).
SELECT currency_code FROM zcurrency
INTO TABLE @DATA(lt_valid_currencies).
LOOP AT lt_orders INTO DATA(ls_order).
IF NOT line_exists( lt_valid_currencies[
currency_code = ls_order-Currency ] ).
APPEND VALUE #(
%tky = ls_order-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = |La devise { ls_order-Currency } est invalide| )
%element-Currency = if_abap_behv=>mk-on
) TO reported-salesorder.
APPEND VALUE #( %tky = ls_order-%tky ) TO failed-salesorder.
ENDIF.
ENDLOOP.
ENDMETHOD.

Collective Value Helps

Pour les champs utilisés dans plusieurs vues, des Value Helps centrales peuvent être définies :

-- Définition centrale de Value Help
@ObjectModel.usageType: {
sizeCategory: #S,
serviceQuality: #A,
dataClass: #CUSTOMIZING
}
define view entity ZI_CountryCollVH
as select from I_Country
{
key Country as CountryCode,
_Text.CountryName as CountryName
}

Elle peut ensuite être référencée dans différentes vues :

-- Dans la vue 1
@Consumption.valueHelpDefinition: [{
entity: { name: 'ZI_CountryCollVH', element: 'CountryCode' }
}]
ShipToCountry,
-- Dans la vue 2
@Consumption.valueHelpDefinition: [{
entity: { name: 'ZI_CountryCollVH', element: 'CountryCode' }
}]
BillToCountry,

Erreurs courantes et solutions

Erreur 1 : La Value Help n’affiche aucune donnée

Symptôme : Le dialogue Value Help s’ouvre, mais est vide.

Cause : L’entité Value Help n’a pas de données ou a un filtre incorrect.

Solution :

-- Vérifier avec SE16/ADT
SELECT * FROM zi_customerVH.
-- Supprimer ou corriger le filtre
define view entity ZI_CustomerVH as select from zcustomer
{
key customer_id as CustomerId
}
-- Vérifier la clause WHERE

Erreur 2 : Les champs supplémentaires ne sont pas remplis

Symptôme : Le champ principal est rempli, mais les champs additionalBinding restent vides.

Cause : Les noms de champs ne correspondent pas ou usage: #RESULT manque.

Solution :

additionalBinding: [{
element: 'CustomerName', -- Doit correspondre exactement au nom du champ dans l'entité VH
localElement: 'CustomerName', -- Doit correspondre exactement au nom du champ dans la Projection
usage: #RESULT -- Ne pas oublier !
}]

Erreur 3 : Le Cascading ne fonctionne pas

Symptôme : La Value Help dépendante affiche toutes les valeurs, pas seulement les filtrées.

Cause : Le champ de filtre manque dans l’entité Value Help.

Solution :

-- L'entité VH doit contenir le champ de filtre
define view entity ZI_RegionVH as select from zregion
{
key region_code as RegionCode,
region_name as RegionName,
country_code as CountryCode -- Ce champ est nécessaire pour le filtrage
}

Erreur 4 : Problèmes de performance

Symptôme : La Value Help charge lentement ou cause des timeouts.

Cause : Grande quantité de données sans pagination ou index manquants.

Solution :

-- Définir la catégorie de taille
@ObjectModel.resultSet.sizeCategory: #XS -- <100 entrées
@ObjectModel.resultSet.sizeCategory: #S -- <1000 entrées
-- Optimiser la recherche pour Typeahead
@Search.searchable: true
define view entity ZI_LargeDataVH
{
@Search.defaultSearchElement: true
@Search.ranking: #HIGH
key KeyField,
@Search.defaultSearchElement: true
TextField
}

Erreur 5 : Erreur de validation pour des valeurs valides

Symptôme : La saisie est rejetée comme invalide, bien qu’elle existe dans la Value Help.

Cause : Sensibilité à la casse ou espaces en début/fin.

Solution :

-- Dans l'entité Value Help
define view entity ZI_StatusVH as select from zstatus
{
key upper( status_code ) as StatusCode, -- Insensible à la casse
status_text as StatusText
}

Erreur 6 : La Value Help ne s’ouvre pas

Symptôme : Pas d’icône ou de dialogue Value Help.

Cause : L’annotation est sur le mauvais champ ou l’entité n’existe pas.

Solution :

-- L'annotation doit être sur le champ modifiable
@Consumption.valueHelpDefinition: [{
entity: { name: 'ZI_CustomerVH', element: 'CustomerId' } -- Vérifier le nom de l'entité
}]
CustomerId, -- Pas sur des champs calculés ou virtuels

Techniques avancées

Valeurs distinctes

Pour les champs avec doublons :

@Consumption.valueHelpDefinition: [{
entity: { name: 'ZI_OrderStatusVH', element: 'Status' },
distinctValues: true
}]
Status,

Arrangement de texte pour Value Helps

@ObjectModel.text.element: ['StatusText']
@UI.textArrangement: #TEXT_FIRST
@Consumption.valueHelpDefinition: [{
entity: { name: 'ZI_StatusVH', element: 'StatusCode' }
}]
StatusCode,

Value Help avec Association

@Consumption.valueHelpDefinition: [{
entity: { name: 'ZI_CustomerVH' },
association: '_Customer"
}]
@ObjectModel.foreignKey.association: '_Customer"
CustomerId,
_Customer

Résumé

FonctionnalitéAnnotation/Propriété
Value Help de base@Consumption.valueHelpDefinition
FiltrageadditionalBinding avec usage: #FILTER
Champs de retouradditionalBinding avec usage: #RESULT
CascadingCombinaison de #FILTER sur les champs dépendants
ValidationuseForValidation: true
Plusieurs VHTableau avec différents qualifier
Performance@ObjectModel.resultSet.sizeCategory

Les Value Helps sont un outil puissant pour des applications Fiori conviviales. Avec la bonne combinaison d’annotations CDS, des scénarios complexes comme les aides à la saisie dépendantes et la reprise automatique de champs peuvent être entièrement implémentés de manière déclarative.

Sujets connexes