Mappiing foreignFields with smartobjects

byuille

New Member
I am writing my first smartobject application. I have created two smartobjects. They both have an sdo I need to map. How do I map them? I have tried putting a DYNAMIC-FUNCTION('setForeignFields':U) call in the child program in the initilazeobjects (overide) procedure. Do I put this code in the sdo or in the window the sdo is in? I don't know how to get the handle of the parent window. I tried setting it with DYNAMIC-FUNCTION('getContainerSource':U). The child program runs but the key fields are not mapped...

Could someone give me a small code example and tell me where in the child program I should place the code...

Thank You,
 
Hi there!

Although you can do this programatically, the standard method of mapping two SDOs together is to modify the data link between them.

Right click on either SDO, choose "Smartlinks..." option, find the data link that joins the SDOs together (or create one if it's not there). Click "Modify..." button. Click "Foreign Fields" button. Highlight the fields on both sides of the join, and click the "Map" button. Then they're mapped!

If you really want to do this programatically, I would recommend that the container should be responsible for the configuration of the join. Never put anything specific in an SDO - you want to reuse the SDO in as many places as possible, and the Foreign Fields mapping may not be suitable the next time you use it! SDOs should just have a very generic query in there, and as much generic validation as possible.
 

byuille

New Member
I didn't state my question properly. I have two smartwindows each have an sdo. For example, one window displays customer info and the other displays orders for that customer. How do I map the sdo's from one smartwindow to the other?
 
Ah, I see. Are you running one window from the other? Well, regardless, here is some code to establish the foreign fields, the data link, and open the child query.

I'm assuming that you can get to the stage of having handles to both SDOs in one place. SDO1 is the Customer SDO, SDO2 is the Order SDO.

RUN addLink ( h_dSDO1,'Data', h_dSDO2).
DYNAMIC-FUNCTION("setForeignFields" IN h_dSDO2,"order.custNum,custNum").
DYNAMIC-FUNCTION("addForeignKey" IN h_dSDO2).

DYNAMIC-FUNCTION("openQuery" IN h_dSDO2).

I would run the first three lines in the Customer window, after you run the Order window persistently and get the handle to the Order SDO. Subscribe to dataAvailable in the Customer SDO and you can then call openQuery in the Order SDO to keep the two windows sync'd up.
 

byuille

New Member
Never assume... :) This is my first smartobject app. How do I get the handles of both sdo's in one place?

Thanks for your help!
 
You're going to have to pass some handles around. Assuming that he Customer window runs the Order window, here's one easy way.

1. Customer window uses RUN wOrder.w PERSISTENT SET hOrderWindow.

2. Create a few procedure in wOrder.w called ipGetOrderSDOHandle (or whatever you want). One output parameter, handle. Set output parameter to be handle of order SDO

3. Back in Customer window, after the RUN of wOrder.w, call ipGetOrderSDOHandle, using some handle variable defined in top level definitions.

So, new procedure in Order window looks like this:

PROCEDURE ipGetOrderSDOHandle.

DEFINE OUTPUT PARAMETER phSDO AS HANDLE NO-UNDO.

phSDO = h_dOrder.

END PROCEDURE.

And the run of the Order window from the Customer window looks like this:

RUN wOrder.w PERSISTENT SET hOrderWindow.

RUN initializeObject IN hOrderWindow.

RUN ipGetOrderSDOHandle IN hOrderWindow(OUTPUT ghOrderSDO).

You now have the Customer window, which already has the handle of the Customer SDO (probably called h_dCustomer - depends how you named your SDO), and also has the handle of the Order SDO. You can now use the code sent earlier to establish the data link and foreign fields.

Hope this helps!

Andy.
 

byuille

New Member
I know that there is no such thing as a stupid question, but I clearly push the envelope sometimes. I combined the code segments you sent me in the customer window in the (Main Block). When I run the customer window I get a message about invalid handles so I added a message box to check which one was causing the problem and it was the handle for the customer sdo. When I run this from the ADM2 shouldn't I be able to reference the handle for the customer sdo or do I have to run the customer window persistently as well? BTW, I never mentioned that I am running 9.1D.

Thanks again,

Barry
 
Blimey - you'll have to bear with me on this one. We may need to bounce things back and forth until it all makes sense.

I'm assuming that the customer window runs the order window. Don't really care what runs the customer window! And apologies if this is teaching you how to suck eggs - not sure how basic it needs to be!

If the handle to the customer SDO is invalid in your code in the customer window, I can only guess that you're trying to reference the handle too early. Each object in a smart container (window, frame, viewer etc) gets instantiated as part of the container's initializeObject procedure (it's buried in the ADM code, drilling down to a createObject call). So, whatever code you have in the main block, I think you should move it to an override of initializeObject.

Go to the procedure list in section editor, and click (New...) button. Select "Override" on the "Type" radio-set. Pick "initializeObject" from the "Type" combo-box and click "OK". Now put your code from the main block in here - AFTER the RUN SUPER statement.

By the time your code runs, the customer SDO will have been created by the ADM2 as part of the initializeObject code, and the handle should now be valid.

Good luck!
 
Top