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: truedefine 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
| Aspect | Recommandation |
|---|---|
| Taille | @ObjectModel.resultSet.sizeCategory: #XS pour petites listes |
| Recherche | @Search.searchable pour Typeahead |
| Filtre | Clause WHERE pour les entrées invalides |
| Champs | N’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
-- Paysdefine 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
| Valeur | Description |
|---|---|
#RESULT | La valeur est retournée |
#FILTER | La valeur sert de filtre |
#FILTER_AND_RESULT | Les 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/ADTSELECT * FROM zi_customerVH.
-- Supprimer ou corriger le filtredefine view entity ZI_CustomerVH as select from zcustomer{ key customer_id as CustomerId}-- Vérifier la clause WHEREErreur 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 filtredefine 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: truedefine 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 Helpdefine 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 virtuelsTechniques 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,
_CustomerRésumé
| Fonctionnalité | Annotation/Propriété |
|---|---|
| Value Help de base | @Consumption.valueHelpDefinition |
| Filtrage | additionalBinding avec usage: #FILTER |
| Champs de retour | additionalBinding avec usage: #RESULT |
| Cascading | Combinaison de #FILTER sur les champs dépendants |
| Validation | useForValidation: true |
| Plusieurs VH | Tableau 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
- Annotations CDS - Aperçu de toutes les annotations CDS
- Fondamentaux RAP - Fondamentaux du RESTful ABAP Programming
- Search Helps - Aides à la recherche classiques en ABAP