Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
GManousaridis
Participant
The task was to hide the fields with null values, on Fiori My Inbox. It may seem pretty straight forward at first, but it can be quite difficult, depending on the complexity of the setup and the restrictions you may have. In our case the restrictions are no tweaking the front end and as less as possible modification of SAP code. Additionally, the attribute that adds up in the complexity of the setup is that we are working on an extend CDS view and not a normal one (definition).

The proposal here is not exhaustive and maybe not the best practice, but... it worked. If you can think of a way to improve this solution, or if you know of other solutions on the subject, please leave your comment.

So, let's dive in:

The solutions that didn't work


These solutions are proposed throughout the community and although they seem appealing, we didn't manage to make them work. If you know anything please share.

Metadata Extension file: To even start considering this solution, one has to be able to create metadata extension file in the first place. To do so, the annotation @Metadata.allowExtensions: true must exist. In this particular case we cannot add it, because it is only possible to be added in regular views (definitions) and not in extend views. The original view does not have it by default, so there is not way to create a metadata extension file here. Out of curiosity we tried to apply the solution to a new custom CDS view on a test environment, but no luck.

Direct assignment: According to this answer, one can directly assign a dynamic value to any annotation, by providing the field in this format: @MY.Annotation:#(field_to_get_value) . We tried this way to make @UI.hidden dynamic, but unfortunately we weren't able to make it work. Maybe @UI.hidden is not supposed  to be dynamic.

External Calculation through BOPF: Using the BOPF framework can possibly be a neat workaround, by providing annotation values through external calculation.

  • Dynamic Field and Entity Field Control: To achieve this, one has to, define the BO View, set annotation @ObjectModel.readOnly: 'EXTERNAL_CALCULATION', for the desired field and use the SET_ATTRIBUTE_ENABLED method to show/hide the field accordingly. This solution is proposed in various answers, has a great documentation article and was confirmed to have been implemented by a colleague on custom CDS views (thanks Ali). Unfortunately, it is possible only in custom CDS views, as one cannot enhance an extend view with BOPF.

  • Virtual Elements (Update 14/03/2021): As mentioned and explained by Daniel Ojados Conesa, virtual elements are another option for external calculation, in order to dynamically provide values to annotations, but unfortunately it utilize the BOPF framework as well. If your CDS view is a new, custom one, then virtual elements, which are again very well documented, will probably work for you.


The solution that did work


Another colleague came up with this solution (thanks Andrei), which is based on the attribute sap:field-control. We made use of the equivalent vocabulary term Common.FieldControl and fortunately we managed to provide the annotation from the backend, through the relative MPC_EXT class.

Common.FieldControl Term


This term accepts a range of integer values which are assigned to different UI utilities. These values can be provided dynamically, by pointing the path attribute to an edm.byte (integer) property.

CDS View


Our extend view part, containing the field to be hidden, looks something like:
source.field as FieldYouWantDynamicallyHidden,
(case when source.ControlField = 'ValueToHide' then 0 else 1 end) as FieldToGetHideOrShowValue

which evaluates to:
<Property Name="FieldYouWantDynamicallyHidden" Type="Edm.String" MaxLength="122" sap:display-format="UpperCase"/>
<Property Name="FieldToGetHideOrShowValue" Type="Edm.Byte"/>

Note that, in our case, we used the values 0 (hidden) & 1(read-only), as the field we want to hide/show is just used for display reasons. In place of 1(read-only), you can add any of the other accepted values, explained above, to suit your needs.

MPC_EXT Class


After redefining and modifying the DEFINE method of the respective MPC_EXT class, of the relative gateway project (maybe not the best way to go, but still legitimate), we add the following piece of code:
lo_ann_target = vocab_anno_model->create_annotations_target( 'YourService.YourEntityType/FieldYouWantDynamicallyHidden' ).
lo_annotation = lo_ann_target->create_annotation( iv_term = 'Common.FieldControl' ) ##NO_TEXT.
lo_annotation->create_simple_value( )->set_path( 'FieldToGetHideOrShowValue' ). ##NO_TEXT.

Note that, for the above code in the define method to work, the following data types and aliases should be present. If not, then you should add them like so:
data lo_ann_target  type ref to /iwbep/if_mgw_vocan_ann_target.
data lo_annotation type ref to /iwbep/if_mgw_vocan_annotation.

vocab_anno_model->create_vocabulary_reference(
iv_vocab_id = 'vocabularies.Common.v1'
iv_vocab_version = '0001'
)->create_include(
iv_namespace = 'com.sap.vocabularies.Common.v1'
iv_alias = 'Common'
) ##NO_TEXT.

And the above code evaluates to:
<Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="YourService.YourEntityType/FieldYouWantDynamicallyHidden">
<Annotation Term="Common.FieldControl" Path="FieldToGetHideOrShowValue"/>
</Annotations>

As you can clearly see, the FieldControl annotation refers to the FieldToGetHideOrShowValue field, to retrieve the value , that we have provided in a dynamic manner, for controlling the UI of the FieldYouWantDynamicallyHidden field.

Another Approach for MPC_EXT


We could implement a code block like so in the DEFINE method of the MPC_EXT class and add the desired term directly as an attribute of the produced oData property:

The backend code would look something like:
DATA(lo_entity_type) = model->get_entity_type( 'YourEntityType' ).
IF lo_entity_type IS BOUND.
DATA(lo_entity_prop) = lo_entity_type->get_property( 'FieldYouWantDynamicallyHidden' ).
IF lo_entity_prop IS BOUND.
lo_entity_prop->set_field_control( 'FieldToGetHideOrShowValue' ).
ENDIF.
ENDIF.

Then the property would look like this:
<Property Name="FieldYouWantDynamicallyHidden" Type="Edm.String" MaxLength="122" sap:display-format="UpperCase" sap:field-control="FieldToGetHideOrShowValue"/>
<Property Name="FieldToGetHideOrShowValue" Type="Edm.Byte"/>

Conclusion


Briefly, what we managed to do here is to implement a code based solution via model provider class (mpc_ext), so as to enable field control capability for the fields of a CDS extend view, in order to show/hide them conditionally.

So, now the system will "see" the field-control annotation for the FieldYouWantDynamicallyHidden field and refer through the path reference to the FieldToGetHideOrShowValue field to get a value telling it whether to hide it or not.

Another possible application of this solution is to dynamically change the field status (hidden, read-only, mandatory, etc) based on user interaction e.g with a checkbox, or another field's value. But for static hiding, it is always advised, that one should use @UI.hidden or @Consumption.hidden like so.

At this final point, I would like to attribute a special thanks to my colleague Panagiotis for his overall guidance through CDS views.

Useful references


Add annotations to an odata service through MPC_EXT

OData Vocabulary Annotations APIs

The attribute sap:field-control
15 Comments
denis_88
Explorer
Great post, Georgios! Thanks for sharing!

GManousaridis
Participant
0 Kudos
Thank you Denis!!
ptheodorog
Discoverer
Very useful post! Thank you for sharing your experience in this task!
GManousaridis
Participant
0 Kudos
Thanks Panagiotis, both for your comment and for your help & cooperation!
WRoeckelein
Active Participant
gmanousaridis13 , thank you for your very helpful post.

Do you or anybody else here knows how to do this is in an umanaged RAP Publishing on Steampunk? Thanks!
GManousaridis
Participant
0 Kudos
Hi Wolfgang,

Thanks for your kind words and sorry for the late response.

No, unfortunately I don't know how this could be performed in the cloud.

George
Hi guys,

I think you can use virtual elements for this.

By using in the target attribute the UI annotation:
@UI.identification: [{hidden:#('virtualElement') }]

and then declare a new virtual element type boolean:
@ObjectModel.virtualElementCalculatedBy: 'ABAP:Z_ShowField'
virtual testField :abap_boolean,

Class 'Z_Showfield' should include interface IF_SADL_EXIT_CALC_ELEMENT_READ

Further info in page 721 of RAP manual 🙂

 

Hope it helps.

 
former_member639226
Discoverer
0 Kudos
Nice. Can this be a solution to make a field read only (on Create/Edit) when it is already saved to the Z table (hasactiveentity)?  Sort of locking the field from changes when this record is already saved in the Z table.
0 Kudos
Hi jaganan

For that purpose, RAP gives you the possibility to use what they call features and control dinamically fields, standard operations and actions. You set up the display and availability of those depending on your requirement conditions.

Further information here: https://help.sap.com/viewer/923180ddb98240829d935862025004d6/Cloud/en-US/dfc68f6275454c41b53510dacae...

 

Hope it helps 🙂

Regards,

Daniel
GManousaridis
Participant
Hello ojados

Thanks a lot for taking the time to propose this solution. Indeed virtual elements are a neat solution, but unfortunately didn't work on this case, as the cds view in hand was not a new, custom view, but one that extends a standard SAP view, providing limited options for further customizations.

Please find the corresponding part of the post which explains the situation and I have updated accordingly, to make it clearer to future readers:
External Calculation through BOPF: Using the BOPF framework can possibly be a neat workaround, by providing annotation values through external calculation. To achieve this, one has to, define the BO View, set annotation @ObjectModel.readOnly: ‘EXTERNAL_CALCULATION’, for the desired field and use the SET_ATTRIBUTE_ENABLED method to show/hide the field accordingly. This solution is proposed in various answers, has a great documentation article and was confirmed to have been implemented by a colleague on custom CDS views (thanks Ali). Unfortunately, it is possible only in custom CDS views, as one cannot enhance an extend view with BOPF.

Please, also check the update and tell me if it is clear enough.

Thanks again for your contribution,

George
jaganan
Explorer
0 Kudos
Thanks dojados , I will keep that in mind.
pmcfarling
Participant

Just a comment. You referenced my question about direct assignment. I have found that @UI.Hidden doesn't work with the #field_name. This technique only seems to work with the hidden property of a FieldGroup (and maybe some others, I tried doing the local annotation of @UI.hidden using the path property and that doesn't work either. )  

GManousaridis
Participant
0 Kudos
Hi Paul,

Thanks for your comment!
Indeed, when I found your content I was excited that I have finally found a solution.
Unfortunately the solution was not applicable to my case.
Thanks again for taking the time to contribute!

Cheers,
George
Mithun_Kumar
Active Participant
0 Kudos
Great suggestion Daniel, but unfortunately as George mentioned this doesn't seem to work for extend views.

I get an error there "Syntax "VIRTUAL" is supported in projection views only" 😞
Mithun_Kumar
Active Participant
0 Kudos
Great article and tips, George. You mentioned
Another possible application of this solution is to dynamically change the field status (hidden, read-only, mandatory, etc) based on user interaction e.g with a checkbox, or another field’s value. But for static hiding, it is always advised, that one should use @UI.hidden or @Consumption.hidden

However, I'm struggling with the hidden property here. I'm trying to dynamically hide or show an additional field in the MyInbox app. So extended the CDS view accordingly.

I tried this way:

in CDS:
I_PurReqnAccountAssignment.MasterFixedAsset,
(case when _Purchaserequisitionitem.AccountAssignmentCategory = 'A' then cast( ('false') as abap_boolean ) else 'true' end) as HideorViewAsset

then in the MPC_EXT -> define method:
    lo_ann_target = vocab_anno_model->create_annotations_target( lv_obje_service_name && '.' && 'C_PurReqnAccountAssignmentType/MasterFixedAsset' ).
lo_annotation = lo_ann_target->create_annotation( iv_term = 'UI.hidden' ) ##NO_TEXT.
lo_annotation->create_simple_value( )->set_path( 'HideorViewAsset' ). ##NO_TEXT.

But nothing happens. The Common.FieldControl term seems to only hide the value of the field, but not the field (label still visible) itself.

Still a n00b at CDS view. Can you see if I'm doing something completely wrong here?
Labels in this area