Richfaces 4 autocomplete component AJAX Value Update - ajax

Trying to migrate a Richfaces 3.3 project to 4. Got to a rich:suggestionBox component and converting it to a rich:autocomplete component, but having major troubles.
Requirements are: fill in part of the autocomplete, it presents user with suitable options. When the user selects something from the dropdown, the component should update it's value, disable itself, and also calculate/update the default value in a secondary field, which the user is able to edit. So far I have this:
<a4j:jsFunction name="jsFunc"
execute="autoComplete"
render="species_name individualUserStr"
actionListener="#{individualsBean.selectedIndividualElem.assignDefaultNickname}"/>
<rich:autocomplete
autocompleteMethod="#{individualsBean.speciesForBox}"
mode="cachedAjax"
layout="table"
var="sp"
id="species_name"
value="#{individualsBean.selectedIndividualElem.userCommonName}"
fetchValue="#{sp.commonName}"
disabled="#{individualsBean.selectedIndividualElem.userCommonName != null
and individualsBean.selectedIndividualElem.userCommonName ne ''}"
onselectitem="jsFunc()"
>
...
</rich:autocomplete>
<h:inputText value="#{individualsBean.selectedIndividualElem.ssi.individualUserStr}"
id="individualUserStr"
maxlength="28"
styleClass="inputTextMediumRF">
</h:inputText>
Right now, when the user selects something the jsFunc is called, assignDefaultNickname is called and everything works fine, except for the fact that the calculation in assignDefaultNickname, used to determine the value of the secondary field, individualUserStr, depends upon the value of species_name, but species_name is not submitted until I submit the form, so the calculation done in assignDefaultNickname is incorrect.
I need to somehow call the setter on individualsBean.selectedIndividualElem.userCommonName, before assignDefaultNickname is called, but I cannot figure out how to do this. There seems to be problems with AJAX and this autocomplete function; that's part of the reason why I have to use this round-a-bout jsFunction component to even call the method in the first place.
Any suggestions on how to solve this?

Found the solution to my own question. Basically, needed to learn how to use the execute attribute. The lesson to any other JSF 2.0 n00bs out there is to use execute to selectively reprocess the page. With execute you can make a white-space separated list of component IDs that should have their values re-bound to the backing bean, in case they need to be used in the listener responding to an AJAX event. In my case, this meant changing the jsFunction tag as follows:
<a4j:jsFunction name="jsFunc"
execute="species_name individualUserStr"
render="species_name individualUserStr"
actionListener="#{individualsBean.selectedIndividualElem.assignDefaultNickname}"/>
As you can see, the jsFunction now, when it is calling the assignDefaultNickname function will first update the values bound to both the auto-complete and the inputText components and THEN run assignDefaultNickname.

Related

How to save a record with validation rule in place

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.

Race condition with Capybara value set

I have faced an issue while using .set(#{value}) to fill the text field in registering form, e.g: the phone number i wanna put in is 506307 then it ended up with 063075.
The work-around i have been made is executing Javascript block like
execute_script("document.querySelector('#{selector}').value = '#{value}'")
However, using the same scripts applying for Webmobile based on React.JS, the scripts above just send the text but didn't send the onChange event, which cause another element cannot be selected/clicked -> made the test failed.
I came up with another approach is to use the send_keys #{value} to trigger the key-pressed event that would make browser think there was a key-pressed event happen for that form, but it ended up with race-condition like set(#{value}) as i mentioned.
The another work-around is using What is the best way to trigger onchange event in react js , but i tend to use the native Capybara actions before making that tricky Javascript.
So, is there any other way to interact / fill the form field which won't cause that Race condition issue ?
Thanks everybody in advance.
Note: Any "solution" suggested that is purely the use of execute_script to run some JS is a terrible idea since it completely bypasses the concept of testing what a user can do and can basically make your test worthless.
The root cause of the issue here is the JS behavior attached to the input not being able to handle the key events fast enough. The proper fix would be to fix the JS, however if that's not possible there's a few things you can try
First you can try changing the clear method being used by set
element.set('506307', clear: :backspace)
or
element.set('506307', clear: :none)
If that doesn't change anything then try clicking on the input, followed by a short sleep before setting the content
element.click
sleep 0.25
element.set('506307')
If none of those work around the issue we need to know exactly what JS behavior you have attached to the input and/or what events that JS behavior is listening to.

Peoplesoft Peoplecode events

i am new to Peoplesoft software and the PeopleCode programming. I have been doing alot of exercises with PeopleCode. I have a question whereby the record fields events such as FieldDefault and etc etc....
I have made an application whereby user can search and add new value. So in a case where I have Peoplecode in one of the event for example SaveEdit, when I click the save button in both cases of search data or adding new value tab, it points to the same PeopleCode.
Is there any method whereby the code will know when user are searching existing data or adding value or rows in PeopleSoft?
Wont it be conflicting for both cases to point to the same PeopleCode?
Another question:
Hi i have a question regarding the passing of variables between the FieldFormula event and SavePostChange.
I have some values being calculated in the FieldFormula and I want to access it in SavePostChange event as I want to prompt messagebox based on the value being calculated.
I have been using the Global variables to access the variables.
Is there any good way to pass the variables or access to the variables values?
In the case of search records, there are a couple of Search-specific events, SearchInit and SearchSave. SaveEdit is when the record is saving so it shouldn't have a conflict with Searchevents.
Additionally you can place code either in the Record PeopleCode (fires every time someone uses that Record in a Component) or in Component Record PeopleCode (just that component). Record PeopleCode fires first then Component Record PeopleCode. The Component PeopleCode also has additional events that the record level ones don't, like SavePreChange and SavePostChange. So once you get the hang who fires when you can get pretty granular control of the various events.
There is actually a pretty good summary in the PeopleBooks here.
Regarding your question of how to differentiate between adding a new value and working on existing one, I would suggest you to use %Mode variable in peoplecode.
When working on existing value %Mode takes the value as "U" ie Update Mode
If %Mode="U" then
/**YOUR CODE**/
End-if;
When working on New value %Mode takes the value as "A" ie Add Mode
If %Mode="A" then
/**YOUR CODE**/
End-if;

Oracle Forms Builder - change to window in another form

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.

Is it possible to pass argument from visualforce apex tag?

I have a function searchWorkByName that takes "key" as an argument and use SQOL to retrieve the data.
In visualforce side, I have a link that calls searchWorkByName but would like to be able to pass argument such as character 'a'
example, (this throws an error)
<apex:commandLink value="search!" action="{!searchWorkByName('aaa')}" />
Is it possible to do so if not what is the alternatives?
apex class
public class SearchWorkTest {
public PageReference searchWorkByName(String key) {
//find record of work names starting from provided key character
workNames = [select name from work__c where work__c.name like 'key%'];
return Page.searchResult;
}
}
visualforce
<apex:page standardController="work__c" extenstions="SearchWorkTest">
<!-- Is it possible to pass argument like 'foo' ? -->
<apex:commandLink value="search!" action="{!searchWorkByName}" />
</apex:page>
You can pass in parameters from a page into a function like this:
<apex:commandLink value="search!" action="{!searchWorkByName}">
<apex:param name="key" value="val"/>
</apex:commandLink>
Obviously, the value of the parameter in this case is fixed. If you want something dynamic (i.e. user types something and that is passed to the function), I'm not 100% sure how you'd do that, but I think it might be possible. However, the solution already posted skins the cat for you, but I thought I'd follow up with an alternative in case it's any use.
No, you cannot pass arguments to actions like that.
1 option is to make this variable a normal form field that user can type text/select from dropdown/whatever - if you'll use same name for a variable in Apex (and make it publicly visible by setters/getters), this will work without problems. Check out my answer at How do I integrate Salesforce with Google Maps? to get started.
Second option - if this search must be somehow done programatically without user having to click anything, if the data for example comes from page itself (i.e. is read in <apex:repeat> tag)... you could make a small helper page & controller and call them as components. There is no problem with passing data to components. Check documentation for <apex:component> and <apex:componentBody>. But I think first answer os most useful for you.
Good luck!

Resources