Home » Developer & Programmer » Forms » WHEN-NEW-ITEM-INSTANCE fires too late (10gR2)
WHEN-NEW-ITEM-INSTANCE fires too late [message #343997] Thu, 28 August 2008 09:52 Go to next message
triddle
Messages: 9
Registered: August 2008
Location: Berlin - Germany
Junior Member
Hello,

I'm totally new to this site and am just posting my first question. I hope someone can help.

In my Forms 10gR2 application, I want to protect/unprotect items dynamically against update
depending on the value of other items. To do this, I have an WHEN-NEW-ITEM-INSTANCE-Trigger,
which will do the following:

IF :<ThisBlock>.<OtherItem> = <Value, which should lead to protection of :system.trigger_item> THEN
set_item_instance_property(:system.trigger_item,
TO_NUMBER(GET_BLOCK_PROPERTY(:system.trigger_block, CURRENT_RECORD)),
UPDATE_ALLOWED, PROPERTY_FALSE);
ELSE
set_item_instance_property(:system.trigger_item,
TO_NUMBER(GET_BLOCK_PROPERTY(:system.trigger_block, CURRENT_RECORD)),
UPDATE_ALLOWED, PROPERTY_TRUE);
END IF;

This works fine for text items. I case of list items, there are some problems. If the cursor is in an other
item, and I mouce click the list items opening button (I have a popup-list) and choose a value, the
WHEN-NEW-ITEM-INSTANCE-Trigger fires much too late. It fires after choosing a value from the list. The chosen value
is already accepted by forms. Any following try to change the value fails like it would be expected when choosing a value the first time.

To work around I tried several things, for example to reset the value to its database value (using
get_item_property(:system.trigger_item, DATABASE_VALUE) in the WHEN-NEW-ITEM-INSTANCE-Trigger. This works, but
additionaly i would need to reset the record status to the value before the popup list value was chosen. At the tiem of trigger invocation, the record status is already CHANGED, so i have no chance to know the record status before choosing the list value.

pre-text-item only fires for text-items, so this is no way. I would need a pre-item-instance-trigger i think, but theres no such trigger.

OK, hope my posting can be understoud, my english is not very good.

Looking forward to helping answers and thanks already

triddle
Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #344443 is a reply to message #343997] Fri, 29 August 2008 16:21 Go to previous messageGo to next message
Littlefoot
Messages: 20894
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
Don't trap it before entering an item which should be disabled; do that in the WHEN-VALIDATE-ITEM of the "this_block.other_item" item.
Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #344744 is a reply to message #344443] Mon, 01 September 2008 02:54 Go to previous messageGo to next message
triddle
Messages: 9
Registered: August 2008
Location: Berlin - Germany
Junior Member
Hello Littlefoot,

thanks for answering.

You said: "Don't trap it before entering an item which should be disabled; do that in the WHEN-VALIDATE-ITEM of the "this_block.other_item" item."

In my case, I don't want to disable the item, I want to protect it from update/insert. So why shouldn't I use WHEN-NEW-ITEM-INSTANCE of "this_block.this_item" Confused ?

A second point is, that the protection causing value of "this_block.other_item" may be a queried one, so I need protection of "this_block.this_item" independant from changing and validating "this_block.other_item" Shocked .

Thank you very much for your answer. Meanwhile, I found the solution Cool :

I use a WHEN-MOUSE-CLICK trigger with the following content:
IF :system.cursor_item<>:system.mouse_item THEN
  go_item(:system.mouse_item);
END IF;


I have attached that trigger on form level. So, if someone enters "this_block.this_item" by keyboard, than WHEN-NEW-ITEM-INSTANCE is called before you can choose a list value, just like it works in text items. if someone enters "this_block.this_item" by mouse coming from another item, the call to "go_item" forces a invocation of WHEN-NEW-ITEM-INSTANCE on "this_block.this_item" before you can choose alist value. If clicking on any text item, forms fires WHEN-NEW-ITEM-INSTANCE BEFORE fireing WHEN-MOUSE-CLICK and :system.cursor_item is alread set to "this_block.this_item", so "IF :system.cursor_item<>:system.mouse_item THEN ..." prevents from calling go_item if not necessary.

Thank you very much again. If my solution passes further testing, I will close the Posting.

So long
TRiddle
Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #344830 is a reply to message #344744] Mon, 01 September 2008 06:08 Go to previous messageGo to next message
triddle
Messages: 9
Registered: August 2008
Location: Berlin - Germany
Junior Member
Hello again Littlefoot,

following correction on the code to WHEN-MOUSE-CLICK:

IF :system.cursor_item<>:system.mouse_item
 AND get_item_property(:system.mouse_item, MOUSE_NAVIGATE)='TRUE' THEN
  go_item(:system.mouse_item);
END IF;



Bye
[EDITED by DJM: fixed crappy formatting]

[Updated on: Mon, 01 September 2008 21:26] by Moderator

Report message to a moderator

Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #344922 is a reply to message #344744] Mon, 01 September 2008 21:31 Go to previous messageGo to next message
djmartin
Messages: 10180
Registered: March 2005
Location: Canberra ACT Australia
Senior Member
Account Moderator
I have read this stuff twice and still don't understand what you are doing.

You can't change the attribute of the 'current' item, therefore, in the When-Validate-Item trigger of the item that determines whether another item is navigable, etc., use the information which has just been changed (you are still in this item even though you are 'leaving') and use it to turn anything else 'on' or 'off'.

Mouse stuff is okay until your users learn how to use the keyboard and then your code isn't actioned anymore.

David
Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #345061 is a reply to message #344922] Tue, 02 September 2008 04:07 Go to previous messageGo to next message
triddle
Messages: 9
Registered: August 2008
Location: Berlin - Germany
Junior Member
Hello DJMartin!


  1. You wrote: "You can't change the attribute of the 'current' item, therefore, in the When-Validate-Item trigger of the item that determines whether another item is navigable"

    Yes, you can change, not all but some attributes!!! The Attribute I'm changing isn't "NAVIGABLE" or "ENABLED". In my text, you will find it is UPDATE_ALLOWED. INSERT_ALLOWED would be also changable. And I'm not changing the item attribute, but the item instance attribute. One can imagine, that items should be disabled, to protect them from update/insert. But I want them to remain navigable, so the user, in case of text items, can copy the value to the clipboard. I want this behavior for all kinds of items by using a standardized code which than has to be applicapable to all kinds of items and the belonging trigger can be attached to the form.

  2. You wrote: "in the When-Validate-Item trigger of the item that determines whether another item is navigable, etc., use the information which has just been changed"

    As I replyed to Littlefoot, the protection causing value may be a queried one, which means the protection should also be applied right after an execute_query, if the user enters the item to be protected.


All this can be done by using WHEN-NEW-ITEM-INSTANCE. As I tried to explain, the only mess is, that in case of mouse navigation to a list item, WHEN-NEW-ITEM-INSTANCE fires after forms accepted the choosen value (a bug in forms, if you ask me). In case of keyboard navigation everything is fine and WHEN-NEW-ITEM-INSTANCE fires before the user can change the value. One thing remains: Forms still allows you to open the list and choose a value, and then complains, that the item isn't updatetable/insertable (maybe also a bug in forms, or the intention to let the user see all possible values).

So the only thing needed to correct this behavior of forms, is a way to force forms to invoke WHEN-NEW-ITEM-INSTANCE before the value can be changed in case of mouse navigation. And this is what I'm doing with the WHEN-MOUSE-CLICK trigger I wrote. The call to go_item enforced forms to do so, just like it is in case of keyboard navigation. As you see, this may only be done for items, which are normally navigable. In addition, I also checked, if the :system.mouse_item and the :system.cursor_item are different. I haven't tested yet, if this is really necessary. It could be, that a call to go_item with the already actual (cursor) item as argument leads forms to do nothing, so the additional check would be needless.

Hope that this explanation was clear enough. Otherwise don't hesitate to write again.

Thank you for your reply.

Have a nice day - TRiddle
Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #345304 is a reply to message #345061] Tue, 02 September 2008 20:53 Go to previous messageGo to next message
djmartin
Messages: 10180
Registered: March 2005
Location: Canberra ACT Australia
Senior Member
Account Moderator
Please continue with your exercise. The rest of us will use post-query and when-validate-item.

David
icon7.gif  Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #345347 is a reply to message #345304] Wed, 03 September 2008 02:57 Go to previous messageGo to next message
triddle
Messages: 9
Registered: August 2008
Location: Berlin - Germany
Junior Member
Hello again DJM!

I'll continue, but I wouldn't call it exercise.

First of all: I corrected the code of WHEN-MOUSE-CLICK as follows:

IF :system.mouse_item IS NOT NULL AND :system.cursor_item<>:system.mouse_item THEN
  IF get_item_property(:system.mouse_item, ITEM_TYPE) in ('BEAN AREA', 'BUTTON', 'CHECKBOX', 'LIST',
                                                          'RADIO GROUP', 'TREE', 'USER AREA') AND
  	 get_item_property(:system.mouse_item, MOUSE_NAVIGATE)='TRUE' THEN
		 KSUI.set_trigger_item(:SYSTEM.CURSOR_ITEM);
		 IF UI_checkBlocks() THEN
	      go_item(:system.mouse_item);
	   END IF;
   END IF;
END IF;




  1. I added IF :system.mouse_item IS NOT NULL cause WHEN-MOUSE-CLICK fire also when you click outside of any item (on a canvas for example)
  2. I added IF get_item_property(:system.mouse_item, ITEM_TYPE) in... cause the following call get_item_property(:system.mouse_item, MOUSE_NAVIGATE) is only applicapable to the listed item types (as the forms documentation also reports)


Now let me think about your suggestion:
Your idea of using POST-QUERY (in addition to WHEN-VALIDATE-ITEM) to cover the mentioned case of protection right after execute_query would be a way too. But let's be careful and look a bit deeper. I'm implementing a standard OLB and belonging PLL, with which other employees in our department can develop a softwaresystem 1) efficently, 2) avoiding redundancies and needles code or calls 3) which is easy to maintain. So one thing I learned in my nearly 20 years as a developer, and over 10 years of that time as a inventor and developer of standard software products is, that reducing redundancies leads to easier maintainable and extendable software. When I think about your idea, the code using that two triggers could look like follows:

PROGRAM UNIT "test_and_set_protection":
      :
IF :<BLOCK>.<PROTECTION_CAUSING_ITEM> = <PROTECTION_CAUSING_VALUE> THEN
   set_item_instance_property(......UPDATE_ALLOWED, PROPERTY_FALSE);
END IF;
      :


POST-QUERY as well as WHEN-VALIDATE-ITEM:
     :
   test_and_set_protection();
     :


Now there is one question: where to attach the WHEN-VALIDATE-ITEM trigger? If you do that on block level, the call to the program unit is done, every time you change any value of the current record/block, even if the user never intends to navigate to the item to be protected or never visits the protection causing item. If the condition leading to that protection includes time-consuming calls to the database server, this could lead to a very slow editing. You will have to avoid needless calls to that time consuming test. One way is to attach WHEN-VALIDATE-ITEM only to the protection causing item. But that isn't easy to maintain in case of changes to the software or changes in the number of input values of that test. So the program unit itsself has to have the chance to decide, if that protection test is necessary. To do that attach the trigger to the block and correct the program units code as follows (like I do in my way using WHEN-NEXT-ITEM-INSTANCE):

PROGRAM UNIT "test_and_set_protection":
      :
IF :system.trigger_item IS NOT NULL OR :system.trigger_item = '<BLOCK>.<PROTECTION_CAUSING_ITEM>' THEN
   IF :<BLOCK>.<PROTECTION_CAUSING_ITEM> = <PROTECTION_CAUSING_VALUE> THEN
      set_item_instance_property(......UPDATE_ALLOWED, PROPERTY_FALSE);
   END IF;
END IF;
      :


Using this sort of program unit, you can implement all of the blocks/records protection tests in it, wich is clearly arranged code and easier to maintain. And the test would be done exactly in 2 cases. 1) in case of call from the POST-QUERY trigger (:system.trigger_item IS NULL) and 2) in case of WHEN-VALIDATE-ITEM trigger fired for the protection causing item. That would work. But, as I mentioned above: If the user never visits either the protection causing item or the item to be protected, the test initiated by POST-QUERY was needles. OR if the user changes the protection causing item, but never goes to the item to be protected, why should I protect it (as a precaution??). And last but not least, the POST-QUERY/WHEN-VALIDATE-ITEM are two places of code, which may be have to be maintained in case of intended software changes. You see, the points 1 to 3 of my text above are not totally reached.

Am I right??


Hope I'm not annoying you.

TRiddle
icon9.gif  Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #345396 is a reply to message #345347] Wed, 03 September 2008 06:58 Go to previous messageGo to next message
triddle
Messages: 9
Registered: August 2008
Location: Berlin - Germany
Junior Member
Hello once again DJM!

After my long explanation of my motives, I was tied down to earth again by the bullshit that forms does. As I said, my main problem was, that WHEN-NEW-ITEM-INSTANCE for a list item fired after the change of the belonging item in case of mouse navigation and choosing a value. And the explained way with WHEN-MOUSE-CLICK works.
Now I tried to convert my list item to a radio group, cause there are only two possible values, which looks better with radio buttons. Maybe you already guess, what happens. In case of a radio group, when you click on a not activated radio button comming from a different item, forms does the following in the following order:

1. Forms changes the Value (as the absolutly first thing, sick!!)
2. Forms fires the WHEN-NEW-ITEM-INSTANCE trigger
3. Forms fires the WHEN-MOUSE-CLICK trigger

I don't want to think about, what forms will do in case of other item types. I expect as many different ways as there are item types. Isn't there anything, one can rely on with forms Mad.

So maybe your idea may have some restrictions as explained in my reply before. But you won't have to deal with the confusing order of trigger invocations and value changes, forms performs.

TRiddle
Re: WHEN-NEW-ITEM-INSTANCE fires too late [message #345497 is a reply to message #345396] Wed, 03 September 2008 20:09 Go to previous message
djmartin
Messages: 10180
Registered: March 2005
Location: Canberra ACT Australia
Senior Member
Account Moderator
Dear Uwe,

I applaud your effort to have a standard solution, useable by all your developers.

I acknowledge that you have "nearly 20 years as a developer, and over 10 years of that time as a inventor and developer of standard software products". I have been coding professionally since 1974 and solely with Oracle Forms and PL/SQL since 1993 (except for 12 months other stuff for Y2K). I started with Forms 3.4, then 4.0 (beta), moving onto 4.5, quickly through 5 to 6.0, back to 2.3 with Oracle Financials 10.7, 6i and 6i migrating to 9i, then 6i migrating to 10g (twice) and now back to 4.5 with consulting on 9i and 10g. This is not to say that I know more than you or that I am better or more of an expert, but to indicate that I may have more experience in this one particular product.

During these last 15 years I have learned that the underlying nature of Oracle Forms has not changed. It is still inherently a block mode, keyboard based system with a few bells and whistles.

I have also learned that keeping things as simple as possible is the safest, most often the fastest, and in the long term, the cheapest way to develop and maintain an Oracle Forms application. During my time I have had discussions with many developers, perhaps experts, quite a few with much more experience than myself and, although I can't say 'ALL' (as I didn't ask them specifically), most of them have taken the philosophy of 'populate a field then decide what to do and where to go'.

I repeat "Please continue with your exercise" but I should have also dsaid "don't put all your eggs in one basket".

Generalised routines are useful and I support your efforts fully. However, developers are paid to be developers, not robots. Specifications should indicate when an item is to be protected and when it is not to be protected. I stand by my recommendation of "use post-query and when-validate-item".

Good luck.

Yours faithfully,
David

<end of communication>
Previous Topic: using EXEC_SQL.Is_Connected
Next Topic: Synatax to call .Net application from When-Button-Pressed Trigger
Goto Forum:
  


Current Time: Mon Dec 05 08:34:29 CST 2016

Total time taken to generate the page: 0.11042 seconds