Cloud for Customer – How to bind EC to a standard screen without using context binding or outports
Probably you know that, in order to pass parameters from a screen to an embedded component, you need to bind your EC context to the main component context, or you need to use an outport containing one or more parameters, from the main component to the EC.
If you are working with a completely custom main component, these kinds of binding are possible, but try to imagine the situation in wich the main component is a standard screen (for example the QC component of an ActivityTask).
This standard component have no outports, and cause it is a standard screen you are not able to bind the EC context with the main component context.
So… have you to give up?
Look at the following procedure, proposed by me, and already approved by SAP Cloud for Customer Development Team!
_________________________________________________________________________________________
Requirement: create an embedded component that can take the existing instance of an object without the need of context mapping and outport parameters.
Idea: when the object (in this example a task) is created or modified, we want to save the instance UUID (that it is not already saved in the persistence layer) in a custom business object, without the need to save it, and then, using the retrieve function as a transformation field in the embedded component (EC), we get the task UUID and we read the existing instance using the retrieve function.
Limits:
- A UI can have only one Business Object mapped on the context.
- A query cannot be used because we can’t save the custom instances.
- It is not possible to save an identifier in a custom field of the task in order to get the BO with a retrieve in the UI because the retrieve doesn’t support custom fields.
- It is not possible to duplicate the standard screen in the embedded component by creating a new instance in the EC and deleting the original instance, because some event handler of the main component work on the original instance (i.e. save and complete).
Useful informations:
Getting started!
Step 1.
Create a business object extension for the ActivityTask standard BO with a dummy field (almost a field is required).
Step 2.
Implement the Event-AfterModify.absl in order to save the task UUID by using a reuse function called WRITE_TASK (to be created in the step 4).
Step 3.
Create a custom BO that will handle the association USERUUID (unique key) to TASKUUID.
Step 4.
Create the Reuse Library with two functions: READ_TASK and WRITE_TASK.
The WRITE_TASK function check for existing instances with the key userUUID equal to the current userUUID. If the instance exists, it will update the taskUUID with the importing parameter, otherwise it will create a new instance.
The READ_TASK function check for existing instances with the key userUUID equal to the current userUUID. If the instance exists it return the associated taskUUID.
Step 5.
Create the Embedded Component with an hidden field TaskUUID binded with the /Root/DataField context node.
You can also add some other fields binded to the context attributes related to the task (see next step). In this example I added task name and task category.
Step 6.
Bind the Root note to the ActivityTask standard BO and add some fields if you want (see step 5). No initialize event handler is required.
Step 7.
Add a new field DataField to the context and set property “Is Dedicated Field” to TRUE (1).
Select a new Transformation Field and choose the READ_TASK function from the custom reuse library (see step 4) (2).
Add an event handler to the event OnValueChanged of this field (3).
Bind the Root element (4).
Step 8.
Check the created Field Transformation (automatically generated).
Step 9.
Create the BOOperation for the event handler using the read (retrieve) operation and add the NavKey parameter as nodeId, binded with the DataField (that will contain the taskUUID).
So when the EC is initialized, the field transformation start, the task UUID is filled, andthe event handler is loaded because of the DataField modification.
Step 10.
Add the EC to the standard QC component (no bindings are required).
Step 11.
You are ready to test!
Open a new task and check that the EC has the same values of the standard component. Try to change some value (and press enter because standard fields have no event handler associated) in order to see the new values also in the EC.
If you want that, by changing the category dropdown, the dependant dropdown automatically changes (withouth the need to press the enter), you have to hide the standard field and let the user to use the replicated field in the EC.
Hey Alessandro!
Thanks for the great tutorial! This is really great as this way we don't have to have an outport 🙂
Really helpfull! In general it would be greate to know more about how to reuse libaries in combination with the UI via transformation. I think it is quite cool 🙂
Cheers,
Jens
Hi Jens,
thank you! I hope that this blog will be useful.
HI Alessandro,
Thanks for the useful information regarding the EC and it was described excellently..
Regards..
Hanumath K
Hi Alessandro,
thanks for the info, it's interesting regarding EC.
Regards,
Joe.
Hi Alessandro,
I have something similar requirement. Here you have discussed about outport but mine is on inport.
My requirement is with Activity BO's QC. Where in I need to pass the ID from the Custom BO to the QC screen. Since the inport is missing I have difficult in doing this.
Is there any suggestions you have.
Hi Alessandro,
Excellent Blog! Hope to see more blogs from you.
Regards
Vinod
Thank you Vinod
Good Blog! Appreciate your time spent on this 🙂
Nice Blog.
it saved my time..:).Appreciate your time spent on this blog.!
Hi Allesandro ,
In the new Actiivity BO of 1402 , SAP seems to be included the UUID type from namespace Common.DataTypes but in the 1311 its from Ap.Common.GDT , So now when i write the task UUID in step 2 its giving me error..since the this.UUID is from Common.datTypes but the importing parameter(UUID) of Write_task method is from AP.Common.GDT, How to resolve or change the above scenario as per the new changes in Activity BO??
I tried to use the UUID namesspace in the reuse library to Common.DataTypes but in the USERUUID Bo , if i change the namespace to Common.Datatypes then its not allowing me to add the promary key in the bo, Could you please let me know the possible solution for this issues??
Thanks,
Mani
Why is not allowing you to add the primary key in the BO?
Use the correct namespace you should not have problems.
Post an error screenshot
I did a small mistake..Now its resolved..!! In the custom BO UserUUID i took it from AP.Common.GDT and TaskUUID i took it from Common.DataTypes namesspace.
Now its working fine..:)
Thanks,
Mani
Hi, Alessandro,
This is really great. This works perfectly when creating a new account.
But doesn't work when editing an existing account.
Is it because of my mistake?
Regards,
May T.
Hi, it should work, but it is better to use the normal approach using the standard outport.
HI, Alessandro,
Great post. Really helpful.
Have two questions?
1. When I edit, the aftermodify is not working, so that the standard BO is not unable to create an instance of Custom BO. How should I do about this?
2.What if the same user create more than one accounts at the same time?
How can I control that?
Please give your advice on those two above.
Regards,
May T.
Hi Fred,
for the point 1 there is not solution. Maybe you can try to trigger the after modify with some dummy automatic operations made with another embedded component.
For the point 2: what do you mean creating more than one account at the same time? With the UI you can only create one object at time, can you make an example?
Hi, Alessandro.
For point 2, what I meant is "creating more than one account at the same time with two windows or taps by the same user". Not a quick create though. I am using your idea on ByD where I can open more than one tap at the same time.
Regards,
Fred
This is not a problem you just need to add as key for the custom BO, the concatenation of user uuid and account id instead using only the user uuid.
Hi, Alessandro,
So, you mean I should concatenate the UserUUID and AccountID.
So, how can I retrieve the instance?
Doesn't that retrieve method works on UUID?
Regards,
Fred
Use two fields:
UserUUID+accountUUID (key) | AccountUUID
Hi, Alessandro.
What you mean is creating a new UUID from the sum of UserUUID and AccountUUID. 🙂
Regards,
Fred
PS. sorry for my stupidity. 🙂
Don't worry you can ask everything!
Exactly, creating a new alternativekey made by sym if UserUUID and AccountUUID, in this way also if you create two Account at the same time you should not have problems!
Thank you so much , Alessandro
Looking forward to your next posts.
Regards,
Fred
Hi Alessandro,
I can't understand your approach for solving the point 2 of Fred. Are you going kind of encrypt an AccountUUID along with UserUUID and then decrypt it (in the READ_TASK function), am I right?
It is somehow mysterious for me, because at that phase (in the READ_TASK) the AccountUUID is unknown. The AccountUUID is actually the parameter which has to be handed over! So as far as you don't know the AccountUUID you can't compose the sum of the AccountUUID and UserUUID in order to Retrieve the USER_TO_TASK Object.
Best regards,
Leonid Granatstein
Hi Fred,
I didn't test this particular app but from my experience opening an UI in the new tab creates a new session. Datas in the buffer memory which are accessed by the Retrieve function are incapsulated, t.i. there are actually one buffer pro session. So from my point of view you won't need an additional key like account uuid.
Moreover, I don't actually see the necessaty to use the User UUID, for the same reason. Alessandro, have you evaluated to come out with a singleton here? It seems to me that you just have to add a BeforeSave action to the Task, where you delete the created singleton to avoid the locking problems.
Regards,
Leonid.
Hi,
I've tested my proposal to use the Singleton Object, and it works fine.
Also this works for the case when one user tries to create different tasks at once.
Merely the idea to delete the singleton object in the BeforeSave event didn't worked out. It's kind of stange, because it is true that all buffers in memory are incapsulated within the session, so the Retrieve from the different Tab or different user delivers no results. The Create is not possible, though. That is not like on the picture "Useful Information" provided by Alessandro.
So I'd to use some other trick to prevent concurrency in the DB, a little bit more complex but also not larger than a couple of script lines.
Leonid
Hello Allessandro,
Horst Schaude mentioned, that your approach might also help me with my requirement. Hence you use the RETRIEVE, which is based on the ID, I am not quite sure, if it really could help me on my requirement (embedding a subset of Opportunities into a Custom-BO Screen).
Could you kindly have a look at my posted question?
http://scn.sap.com/thread/3588006
Thanks in advance and best regards
Tom
HI Alessandro,
Thanks for this nice blog, But i have one more question . Is there any way that instead of putting that EC at the end we can able to place it somewhere in between at a specified place according to the requirement ..
thanks
Debasis
Unfortunately not 🙁 You can place ECs only where you have the standard anchors
Thank you .for the response ..
As expected ...
Hello Alessandro,
I am trying to do something similar to your model, but I am facing an issue with the custom functions.
When I try to Retrieve an instance of my custom BO in the WRITE.absl, all my fields are read-only. I cannot change their values.
The weird thing is these custom fields can be modified from other script files:
- in before-save of an .xbo. with a Retrieve on my custom BO,
- in the After-Modify of this custom BO,
- but all my custom fields are read-only in the function WRITE.absl...
Do you have any clue on this?
Thank you very much for your attention.
Best regards.
Jacques-Antoine
hi, check the deployment unit for the reuse function
Another thing: check that the reuse function is write enabled
Hi Alessandro,
I realized all steps with this tutorial, but for my project it doesn't work very well...
At step 10 I would like to Add the EC to the standard ODT_ExpenseReport_HTML_EC.EC.xuicomponent but i don't find my custom EC.
I tried also with others floorplans but didn't find too.
Could you tell me any advise?
Thanks,
From your screenshot i see two pane containers. Try the second one.
There are 3, but all of them don't show any EC...
In this case better to raise an incident. Maybe there is some problem with the standard anchor
Hi,
I've implemented this tutorial and I've seen that some steps need clarification or correction. This is mostly because of the changes since the older releases of the Studio.
I've used C4C 1511. I've writen down the details on how I adopted the solution provided by Alessandro. The following applies:
0.
The solution has to be preferrably in the Foundation deployment unit.
the deployment unit of the BO USER_TO_TAK has to be "Foundation", otherwise it is not possible for the function "WRITE_TASK" from the CUSTOMER_REUSE library to write into this BO
The easy way to achieve this is to create the solution in the foundation deployment unit
On the Step 1.
The BO ActivityTask from the namespace AP.FO.Activity is deprecated, you have to take the BO Activity from the namespace AP.PC.ActivityManagement.Global instead
Dummy field in the activity extension isn't required any more, the extension is possible without elements
On the Step 4.
The parameters UUID in the Reuse library "CUSTOMER_REUSE" for both functions "READ_TASK" and "WRITE_TASK" should be not of type "AP.Common.GDT" but of the type "Common.DataTypes" to be compatible to the UUID of the BO activity; the same goes for the element "taskUUID" in the VO USER_TO_TASK
On the Step 6.
Instead of the element Activity.Name for the EC field you can take Activity.SubjectName
On the Step 7.
You don't have to add the DataField to the context since it has already been added in the Step 5.
Best regards,
Leonid
thank you leonid. It is true this blog was referring to the old 1311 version and many things changed in the meanwhile
Hello,
I am on 1605, I just wanted to say that for me all the data types that are related to UUID sshould be "AP.Common.GDT", so is not necessary to change them.
As you said I create my custom BO in Foundation deployment unit.
Like below:
[DeploymentUnit(Foundation)] businessobject Custom.BO {
....
}
Regards,
Sin
Thanks Alessandro,
Very useful!
Dear Alessandro,
thank you very much for the tutorial. It is extremely helpful to know that binding of an embedded component can work without inport/outport parameter configuration and their binding.
The only issue I have is the WRITE UUID function, because it doesn´t update the UUID of an existing instance. I tried your approach for the Customer BO. After the first instantiation of the UUID with the same user uuid, I am not able to update the value and therefore the first created instance always appears in the embedded component. I also debugged the Code, I can see that the new value of UUID is written into the datafield but with no persistence. Maybe you know something that could support me with my issue.
Example:
instance.CustomerUUID = CUSTOMER_UUID; ---->it doesn´t update the value
Best regards,
Rufat