Is it possible to get default item value using plsql? I have a validation and in case it fails I want to reset item to its default value.
I tried using apex_util.set_session_state('P_ITEM_NAME', null) but that did not have any noticeable effect.
How can default item be retrieved or item itself be reset?
When creating a page process, there is a condition called "Inline validation errors displayed", maybe this will help? In this process you can reset items to null, then when page loads, item values will return to their default values.
UPD:
Create process:
Process Point: On Load Before header
Condition: Inline Validation Errors Displayed
Process source:
begin
for i in (
select t.ITEM_DEFAULT, t.item_name
from apex_application_page_items t
where t.application_id = :APP_ID
and t.page_id = :APP_PAGE_ID
) loop
apex_util.set_session_state(i.item_name, i.item_default);
end loop;
end;
This will return all page items to their default values.
This solution some ugly, but i don't know another solution for this problem.
:P_ITEM_NAME := null;
The difference here is the ":" infront of the item. Using it like this will give access to the item. Using apostrophes isn't needed I believe.
If this doesn't work with your version try without the ;.
So you can use:
:P_ITEM_NAME
To get the value.
I could not find any function that would return me default value using an item. However I could use default item setting to mimic this. Page processes do not run when page has validation errors, so I added conditional page process that performs the same checks as my validation and when these checks indicate that validation fails it just clears item state.
This is ugly as it requires checks to be duplicated and it seems that it is necessary to replicate almost same page controls through all pages where such reset mechanism is necessary.
Related
I have an array of FormControls in an inventory application in which I am trying to update a single item in the form based on a change - by another user on another device - in the value in the back end. (Firebase in my case.)
I have access to the FormControl and I am able to make that change... except not. Here's the situation:
You'll not from the console output, that when I expand the FormGroup and look at the value I see 3. This is the correct value from the back end. But the FormGroup.controls.current.value is still 4... the old value in the form.
I've been trying to play with different methods of accessing this control to get it to update properly.
Here's the code:
this.items.controls.forEach((item, index) => {
if (item.value.current != this.inventoryElements[index].current) {
//First attempt to change the value of the formControl
this.items.value[index].current =
this.inventoryElements[index].current;
//Second attempt
this.items.controls[index].value.current =
this.inventoryElements[index].current;
//Third attempt
item.value.current = this.inventoryElements[index].current;
console.log(this.items.controls[index]);
console.log(this.items.controls[index].value.current);
console.log(this.items.value[index].current);
}
});
this.inventoryElements[index].current holds the value I want to put into the form control.
this.items is the array of Form Controls.
You can see that I made three attempts to get the value there without luck -
The first console.log results in 4.
The second console.log results in 4.
The third console.log results in the output pasted at the top of this question.
One more piece of background. The FormArray is this {current: string, notes: string} and my attempt was to modify the current value.
By the way, the reason I'm going through all of this mess is that I was unhappy that an update of a single value in the back end would cause the entire page to reload. So this was an attempt to see whether I could update a single value and avoid the whole page reload.
Thanks the the help.
Paul
The third attempt was close. Instead of assigning the value with an equals sign:
item.value.current = this.inventoryElements[index].current;
Use patchValue
item.patchValue({
current: this.inventoryElements[index].current});
I am trying to set a value of a page element on page load in the beginning.
The value is dependent on another element that has already been retrieved from the DB and is already set at the beginning.
To set the id I created a function and I call this function for the dynamic action on page load like this:
declare
id number;
begin
id:= set_ID(V('P1_page_item'));
apex_util.set_session_state('P17_ID',id);
end;
However the value for the page item is not being set.
Do you have any suggestions how an page item value can be set on page load?
There are many ways to set the value of a page item on page load. You can use a page process, a computation, a default value for the page item or a source value for the page item. A dynamic action is a possibility as well, but I have never done that...
Personally I find a computation the cleanest way of setting a value to a page item. It is meant just for that - computing a value for an item. In your case, you could create a computation for item P17_ID of type expression with source set_ID(:P1_PAGE_ITEM)
Now the problem of the page item not being set is probably something else. Try to give as much information as possible about the page to give us clues as to why this is not being set correctly. Have you run the page in debug ? That should give you an idea of what is happening.
On a side note:
The function V should not be used in an application. It was created to allow referencing of apex item values outside of the context of an application, for example in a stored procedure or a view. Using the V function has performance issues and should be avoided if possible. In the application, just use the bind variable syntax (:P1_ITEM) to reference and set variable values.
How is P1_PAGE_ITEM being set ? As a best practice try to avoid referencing page items on other pages. P1_PAGE_ITEM should only be referenced and manipulated on page 1 and so on. Using branches or links you'd then set a corresponding item P17_PAGE_ITEM on page 17. This will save you a lot of debugging time later on. Also, if you clear cache on page 1, then the value of P1_PAGE_ITEM will be wiped out which could lead to unexpected behaviour if that page item exists on other pages.
I'd use
id := set_ID(:P1_PAGE_ITEM);
Also, did you set dynamic action to fire on initialization? I presume you should.
I currently have a validation rule that prevents user from making changes to a record when its status is completed. Users are only allowed to make changes if the status is either draft or registered.
AND(
TEXT(Current_Status__c) <> "Draft",
TEXT(Current_Status__c) <> "Registered"
)
There is a new requirement to allow user to update only a specific picklist value field even if the record status is completed. If i remove the validation rule, user will be able to change any fields on the page layout which won't work.
Object setting for the profile is read, create, edit. This object is a child object to Opportunity, OWD is controlled by parent.
Any recommendation on how to solve this issue ?
Thanks in advance.
We can rewrite your rule as ISPICKVAL(Current_Status__c, 'Completed') for example, looks bit cleaner. Your call though, you can keep as is.
So what you'd need is something like ISPICKVAL(Current_Status__c, 'Completed') && !ISCHANGED(Some_Picklist__c). It should let the edit through if you're modifying that picklist.
The problem is it won't check if that's the only change. Usercan cheat, modify 10 fields and they'll "piggyback" and save OK as long as one of them is that picklist.
It's pain to write validation like ISPICKVAL(Current_Status__c, 'Completed') && !ISCHANGED(Some_Picklist__c) && (ISCHANGED(Field1__c) || ISCHANGED(Field2__c) || ISCHANGED(Field3__c)). You'd have to add all editable fields to it, change it every time you make new one. And eventually you'll hit length limits.
I know 3 options for this if it's a concern for you:
Ask a developer to rewrite your logic to Apex trigger, it could then go dynamic through all fields (using "describe" calls to learn field names or stuff like getPopulatedFieldsAsMap.
Another trick is to allow editing completed records only through a quick action, not normal edit page. In that action you could set some hidden checkbox in the field prepopulating step and your validation would let the save through only if that checkbox is set. But then you need to deactivate it somehow anyway or the bypass will get permamently enabled.
If you don't have too many record types on the object a common trick is to change the record type on completion (workflow, process builder etc). And have another page layout with all fields locked down except that special picklist. It works good enough for UI changes but won't protect if you have code and integrations writing to the object too.
Everytime my page comes up it executes the table query. I tried doing this,
https://blogs.oracle.com/shay/entry/preventing_queries_when_page_f
but it still happens. How can I fix this? I've tried setting the refresh condition to never, but then I can't get any data back. I'm using JDev 11g.
Thanks.
I can share how I did this in JDeveloper 12.1. I am not sure whether it works in 11g. Nor am I sure it's the best way to do it. But it worked for me.
The idea is to not prevent the initial query execution, but, rather, to make sure it happens quickly and returns no data. The approach is to set the initial query criteria in the View Instance of your Application Module.
This approach assumes you have at least one bind variable in your view object. If you do not, you will need to add one just for this.
Double click on the Application Module
Click on the "Overview" tab at the bottom
Click on the "Data Model" tab on the left, so that you are viewing the Data Model Components of your Application Module
In the "Data Model" tree on the right, click once on the View Object Usage ("MyObjectVO1", e.g.).
Click the "Edit..." in the upper-right corner of the Data Model tree.
Here, you can specify view criteria to be used initially for the page. So,
* Set an initial parameter that will (A) execute quickly and (B) return no data
Then, later, programatically reset the bind variables to correct values that will return data, when you are ready to let your query run.
The most simple way i know is to set up correctly "Refresh" attribute on iterator in the page definition.
To do that set refresh=ifNeeded, then set RefreshCondition with expression language, something like this: #{viewScope.yourBean.refresh}
public class YourBeanClass {
private boolean refresh = false;
public void someAction(ActionEvent actionEvent) {
//some custom logic to set refresh flag
refresh = true;
}
public boolean isRefresh() {
return refresh();
}
}
With this code you can simply manage the moment when you need to refresh your model.
While these solutions will work to prevent the query from executing, I would ask what is the use case that a user sees a table appear on a web page without doing a search first?
ADF is built to query automatically because normally a web page will have an af:query or af:quickquery component on the page to allow the user to enter a query. Once the query is executed, the results are returned and populate the table or form (depending on the page design). Including either of these search components on the page will prevent the page from executing the query until the search is executed. You can also execute a query on entry to the page using a taskflow and adding an Execute operation from the data control to the navigation into/prior to getting to the page.
Note that Shay's blog post is from 2009 and covers the use case of not using a search component and instead uses Execute with Params. Is this what you are using? Saying more about your use case would be helpful.
We have two forms so far, and need to switch from window1 in from1 (which is login screen) to windowX in formX using button (trigger code below):
begin
show_window('windowX');
go_block('some_block_in_formX');
end;
This gives error FRM-41052: Cannot find Window: invalid ID
So question is, should I add formX into show_window parameter in certain way or is there another approach? Thank you.
Please note, that forms are in different files.
that forms are in different files.
If the forms are different files, you need to call the other form using open form/call form/newform - whatever suits your needs.
show_window/go_block sequence can be used only when you're moving to different windows/blocks of the same form - and the error message
error FRM-41052: Cannot find Window: invalid ID
is complaining that it can't go to that Window because it's in a different form.
Each form effectively has a private namespace for all its windows, blocks, items, etc - and your code always runs within the context of a single form.
To solve this, you'll need a form parameter, plus some code in the other form, e.g.:
in formX, add a parameter ACTION
in form1, pass the value 'XYZ' to ACTION
in formX, in the WHEN-NEW-FORM-INSTANCE trigger, check if :PARAMETER.ACTION = 'XYZ', and if so, do your show_window and go_block. Copy the same code to your WHEN-WINDOW-ACTIVATED trigger.
Of course, you'll need to think about the name of the parameter (e.g. ACTION) and value ('XYZ') that will make sense to people maintaining your forms in the future.