This is a test message to test the length of the message box.
Login

Script: Recycling-Heroes - Create by Factory Actions (Contact) [015]

116

In this episode, we'll cover factory actions, late numbering, and number ranges. Finally, we'll complete the UI and navigation and address better error handling.



Introduction

In the last episode, we prepared the UI accordingly and implemented some restrictions with virtual fields. However, one problem still remains in the UI: when we create a new record, the type is initially unknown, and this causes fields to be displayed that should actually be hidden. Therefore, in this video, we will discuss the various factory actions.

 

Actions

So let's start. We create three new factory actions in the behavior definition. We define the action as static, since we want to create a new entity at any time and it is not dependent on any other entry. We give the action an appropriate name and define the result set. An action always creates exactly one new entry. Then we define the permissions for the action. "Global" therefore means that when the application starts, the permission for the action is defined, which determines whether the current user can execute it. We then copy the action and give each a descriptive name. Using the "Quick Fix," we then generate the implementation, format the class, and activate both objects.

Now we need to publish the actions in the Consumption View so that our application has access to them. We can do this using "Use Action." To see the action in the UI, we need to display it via the Metadata Extension. It doesn't really matter which field we do this for. Here, we define the actions for the ContactID on the LineItem, since we want them in the list. In addition to FOR ACTION, we define the actual action to be called and give it a label that we can translate later. Finally, we activate the objects.

If we now go to the UI and refresh the application, the actions will be displayed next to the standard "Create." This completes the creation and implementation up to the UI.

 

Implementation

Next, we can implement the actions using an "auxiliary class." This auxiliary class is connected to the RAP object and allows us to outsource functions from the local implementation to keep it clear. Then we create the global class with the name. Unfortunately, there is no support for this from the ABAP Development Tools. In the global class, we define the connection to our RAP object using the "FOR BEHAVIOR OF" addition. To make the error message disappear, we activate both objects.

We can now begin implementing the class. To do this, we start in the Create method for the address, create an instance of the class, and process the passed keys. We pass the CID and the draft indicator to the method using a new method in the class. We also pass the contact type so that we can create a new contact. In the method, we create a new entry for our RAP object using an EML statement. Since we are using a helper class here, we can also use the IN LOCAL MODE addition. We use a VALUE statement directly for the attachment. Since we want to return the MAPPED structure, we create a type in the class, which we can then define as a RETURNING parameter. Now we pass the information to the EML statement. We need the CID from the action, as this is pre-filled by the framework. We also adopt the draft flag to create the data record in the draft state. Since we want to set the contact type, we adopt it from the parameters. Don't forget that the CONTROL flag must also be set. Once we're done, we activate the class.

Now we can define the method in the local implementation and fill in the individual parameters. For the contact type, we use the constant interface and finally insert the new data record into the mapped structure. Once we're finished with this method, we can copy the call and adapt it for the other methods. This completes this implementation. Finally, we go to the UI and refresh the application. If we now create a new address, we land on the object page. The address type is already pre-populated, as is the icon. Since the unnecessary fields are also hidden, we can start filling them directly.

 

Late Numbering

In the next step, we want to implement late numbering. The data record should only receive its number when the user clicks Save and the data is determined. To do this, we add the LATE NUMBERING suffix to the definition. However, we now also need to recreate the draft table, as the DRAFTUUID is required in the table. Once we've done that, we can activate the artifacts. We can implement the method in the Saver class using the Quick Fix.

In this case, we want to use our helper class again and create an instance for it. In this case, we need to loop over the MAPPED records and fill the ContactId. To do this, we call our new GET_NEW_NUMBER method and pass the PID, which we'll need shortly to read the data. In this case, we create the method using forward navigation and do not start it in the helper class.

Next, we read the contact type from the buffer using an EML statement. Since we only process one data record at a time, we read the first data record to process it later. Then we map the type to the respective constants of the interface. We first return the type as a dummy so that we can test the logic in the next step. If we create a new address in the application and save it, an ID is generated and set.

 

Number Range

To generate correct numbers, we use a number range object to generate such numbers in the system. The numbers should begin with the first letter of the contact type and then a nine-digit number. Therefore, we create a new domain for generating the numbers, which, however, only has nine characters. Next, we need the number range object, which we find via the search. Since the number range object only allows 10 characters for naming, we have to restrict ourselves somewhat to create a descriptive name. In the number range, we use the domain we just created to define the length of the numbers.

After activating, we switch to the Launchpad and enter "Manage Number Range Intervals" in the application to define the various intervals for our number range. In total, we need three intervals, which we want to use later for generation. We will then use the intervals 01, 05, and 09 for the different types.

Next, we implement the number assignment in the method. We gain access to the number assignment via the CL_NUMBERRANGE_RUNTIME class. To do this, we adopt the return values via inline declaration and define a separate variable for the interval. In this case, we can hard-code the object, as it will not change. Now we set the interval depending on the contact type. Employees are created in the 1-number range, customers in the 5-number range, and addresses in the 9-number range. Since we want to include the first part of the type in the number, we use the substring function and read the first character. We then concatenate this with the new number to obtain our ID. Since the number is generated as a NUMC and has a greater length than our data type, we first need to perform an internal mapping.

Finally, we run a test and create a new address. To do this, we enter the first name and last name and save the new address. A new contact ID is now automatically generated, which comes from the range 9 and begins with A. This means we've also implemented automatic number assignment, but only when the data record actually needs to be saved.

 

Refactoring

Now let's perform one more refactoring. We have some points in our logic that we're not using, exceptions that we aren't yet catching, and no messages that we're passing on to the UI. Therefore, we'll create a new return type. This time, in addition to the number, we want to return a Log object that contains possible messages. Therefore, we'll define a structure with two pieces of information.

Then we pass possible exceptions from processing to the log. The ADD_MESSAGE_EXCEPTION method is used for this. Essentially, we need to create the log at the beginning to prevent any errors during filling. Then we capture the two exceptions when using the standard class and pass the messages to the log. Finally, we pass our new number to the new structure as a result. If the return code is set by the method, then there was also an error, such as the number range being full. In this case, we want to create a T100 message. Now we create a new message class for the software component and give it a name. Then we define a message with placeholders, which we then fill during processing. To do this, we use the ADD_MESSAGE method to create and save a simple T100 message.

Finally, we need to adjust the ADJUST_NUMBERS method. Here, we save the result in a new variable, pass the new number to the field, and append all messages to the OTHERS table as RAP messages.

 

Finalizing the UI

Let's adjust the UI one last time. We want to see the full name as the title on the object page, so we transfer the field to the consumption view and activate the changes. We then display the field in the title. The next step is to define the semantic key for the ContactID in the consumption view. This change means that the ID is now highlighted in bold in the list report. If we now look at the object page, we will find the full name in the header. If we create a new record and exit without saving, the draft will remain. Thanks to the semantic key, we can now see the draft instance in the list, as well as some information when we hover over it with the mouse.

 

Create

One open point remains, however. If we look at the list report, we currently also find the standard "Create" action for creating new contacts. However, we don't want to use this, as the app uses the three actions for specific forms. There are currently two solutions available.

We can use "Create" Set to Internal, so the action can no longer be triggered externally, i.e., neither via the UI nor via EML outside of the behavior implementation. To do this, we need to adjust the definition and remove the permissions. In the Consumption View, we need to deactivate the usage, as the action is no longer available externally. If we then reload the UI, only our factory actions will be displayed.

The second alternative is to simply deactivate the button in the UI by deleting the action in the Consumption View. This means that the action is no longer available in the app, but we can still use it via EML. Therefore, we opt for the second version and hide the button in the UI.

 

Summary

We can now create new data records using factory actions and thus set the contact type directly upon creation. This immediately hides the corresponding fields, allowing us to fill in the fields relevant to us. Finally, we finalized the UI and completed the internal error handling so that any errors are passed through to the UI and our application remains stable. In the next episode, we'll validate the input before we move on to creating the application.

Thanks for watching and see you next time.

 

YouTube
Video


Included topics:
YouTubeScriptRecycling-HeroesFactory Action
Comments (0)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Tuesday and Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


017: Core Data Service [Basics] - Creation and Structure

Category - YouTube

In this episode, we'll start with the basics of developing Core Data Services. We'll create a CDS view for a first table and look at the structure in detail.

09/22/2025

Script: Recycling-Heroes - Validation and Determination (Contact) [016]

Category - YouTube

In this episode, we'll ensure that the entered data is properly validated and that we only accept complete records into our app. We'll also implement a first interface for loading address data and refresh th UI with side effects.

09/14/2025

Script: ABAP Tools - Update your IDE [014]

Category - YouTube

How can you view your current version in the ABAP Development Tools, find the update settings, and perform an update? In this video, we'll go into the various details.

08/24/2025

Script: Recycling-Heroes - Virtual elements for UI Features (Contact) [013]

Category - YouTube

How can you use virtual fields to provide additional information to the UI and even influence existing fields? In this episode, we'll explore various aspects of virtual fields.

08/17/2025

Script: Recycling-Heroes - Value Helps and Texts (Contact) [012]

Category - YouTube

What's missing from the Contacts app to make it usable by end users? Basically, it just needs a bit more convenience, more value helps and a search function for values.

08/10/2025