Toggle inputTextarea editable with ajax but can not submit its value - html

I have encounter a problem on First toggle inputTextarea editable with Ajax, how to submit typed in value after toggle The UI build on JSF 2 and RichFaces, the backing bean is #ManagedBean /#RequestScoped for now, contain all necessary properties(indicator/reason) and corresponding get/set methods. The app is running on IBM websphere. I was first taken example from here and here.
The myPage.xhtml related section is
<h:form id="myPage">
<td>
<h:selectOneMenu value="#{myPage.indicator}">
<f:selectItem itemValue="Y" itemLabel="YES" />
<f:selectItem itemValue="N" itemLabel="NO" />
<f:ajax render="reason" />
</h:selectOneMenu>
</td>
<td><h:inputTextarea id="reason" value="#{myPage.reason}" disabled="#{fn:toLowerCase(myPage.indicator) != 'y'}">
</h:inputTextarea>
</td>
<td>
<h:commandButton value="Update" id="update"
action="#{myPage.update}">
</h:commandButton>
</td>
</h:form>
The function here is using selectItem "indicator" to toggle whether inputTextarea "reason" is editable or not. I use <f:ajax> to render, the effect can be seen directly when I toggle on GUI.
When I set "indicator" as Yes, "reason" becomes editable, then I type in some words and click "upload" button(which is a normal post method contain logic to commit form value to database), but the words in "reason" not commit to database.
What I suppose is <f:ajax> set render attribute point to inputTextarea "reason", which means a request already generated when I toggle the selectItem "indicator", but this request hold nothing, because the sequence here is first toggle then available to type in words, the "reason" contain no words at toggle time. And as this inputTextarea "reason" set as ajax render, the normal submit form way trigger by "upload" button also cannot commit its value even I click after type in words. Is this a right guess ?
If this is the right guess, how to solve this issue(e.g how to collect this inputTextarea "reason" value after its become available by ajax toggle) ? Create backing bean listener method with <f:ajax render="reason" listener="...">(and if yes, please show some detail actions I should add for this listener) ? OR any other way(e.g should I go with JavaScript or JQuery to solve) ? If what I did wrong way, please help me to figure out(initial goal is to toggle inputTextarea to editable like ajax effect and then submit the value later typed in).

Maybe this question is a little fuzzy, I want to re-declare it here as: There is an indicator control a related inputTextarea editable or not, but if I just use Ajax render attribute to control this, I cannot use Ajax to retrieve the later typed in words in this inputTextarea, as ajax is acutally a request send from client to server side, when i toggle the indicator to make inputTextarea editable, the request already send out, but no words contained in request at this time, so I stuck here, can not find way to use Ajax to toggle and send later typed in words.
Still welcome if anyone come to an idea with JSF Ajax way.
I fix the issue with using javascript instead of Ajax, the fixed way is a little interesting, as to simulate Ajax effect, need to trigger javascript function in different cases(a combination usage of same javascript function):
1. First, the javascript to toggle "reason" inputTextarea based on indicator, retrieve these DOM elements based on 'formname:element_id', in my question, already show "indicator" as h:selectOneMenu, and "reason" as h:inputTextarea.
<script type="text/javascript">
function handleDisabledOrNot() {
var currVal = document.getElementById('myPage:indicator').value;
if(currVal == "N") {
document.getElementById('myPage:reason').disabled = true;
} else {
document.getElementById('myPage:reason').disabled = false;
}
}</script>
2. Then call this function on indicator with onclick event
<td align="left"><!-- Use onclick event to control whether reason disabled or not -->
<h:selectOneMenu id="indicator" value="#{myPage.indicator}" onclick="handleDisabledOrNot()">
<f:selectItem itemValue="Y" itemLabel="YES" />
<f:selectItem itemValue="N" itemLabel="NO" />
</h:selectOneMenu></td>
3. Finally check the status when load page or work in the page on reason with onblur / onfocus event, to make sure full-scale detect indicator status in the view, otherwise, it will miss status checking in either way. E.g, when first time load the page, if missing check status with onfocus event, if you move mouse into reason inputTextarea, no matter what indicator is Y or N, it is editable initially, to avoid such case, should use onfocus event to check, and vice versa to use onblur event.
<!-- Use both onblur and onfocus event to detect indicator status full-scale on view -->
<h:inputTextarea id="reason" value="#{myPage.reason}" onblur="handleDisabledOrNot()" onfocus="handleDisabledOrNot()">
</h:inputTextarea></td>
Finally, it shows the same effect as Ajax render way. As the link i quote in my question, I know in JSF, the best solution is using Ajax to work with backing bean, but as I don't know how to implement after Ajax toggle, how to collect data in inputTextArea later typed in, I can not come with solution on Ajax way now. So, still welcome some idea based on Ajax, if not, just show purely javascript way here.

Related

Primefaces "reset fail" example

The documentation on the Primefaces showcase page gives a number of examples for ajax and non-ajax reset buttons. One is called "reset fail" and it can be found here. It simply involves calling an actionListener which sets all relevant backing bean fields to null.
I tried "reset fail" and it seems to do the job. So why is it a "fail" example and why do the docs say it "won't work"?
Thanks!
OK try this...
On that Showcase demo page enter "a" in the first field and "bbb" in the second field and press "Submit". You will get a validation error.
Now press "Reset Fail". See how the first field is still highlighted RED as validation has failed?
Now press "Reset Tag" and you will see the RED highlighted field go away.
So the difference is the Reset Fail doesn't reset the validation failures and Reset Tag does.
In the end, a combination of actionListener= and resetValues="true" worked for me, i.e:
<p:commandButton value="Reset" actionListener="#{otb.resetFail}" process="#this" update="#form" resetValues="true" style="margin-left:20px;"/>
Without the actionListener my fields don't clear properly. But the resetValues attribute is needed to get around the validation issue. I got this idea from the StanL answer in this post.
One more thing - in contrast to the example in the PF demo, my bean's "resetFail" method just nulls out the fields. It does not call PrimeFaces.current().resetInputs("form:panel"); (I don't have that library). Still, it works fine.

How to fill Primefaces Autocomplete from Managed Bean

I have a primefaces autocomplete which is shown below:
<p:autoComplete value="#{consultaEventoCargoMBean.idUaSelecionada}" completeMethod="#{consultaEventoCargoMBean.completeUADestino}" var="ua" itemLabel="#{ua.name}" itemValue="#{ua.id}" forceSelection="false" appendTo="#this" />
Where idUaSelecionada and ua.id are Integer and ua.name is a String.
My issue is when I load my page to update the data. My idUaSelecionada is already filled and a object ready to be passed as suggestion (it would be a list of a only element). I was not able to find a way to fill this autocomplete - at least the text component.
Reading the Autocomplete souce code, I saw that there is a List called suggestions. Although there is not a setter for this list, it has a getter. But if I try something like autocomplete.getSuggestions().add(...) I get a NullPointerException. The only way I found to fill this list is through the method indicated by completeMethod tag attribute, who receives a String and returns a List.
I was not able to find in internet how to fill this List. That's why I am asking this to see if anyone has any answers.
Thanks,
Rafael Afonso
You can use JavaScript to trigger execution of method defined in completeMethod tag attribute and load suggestion(s).
Supposing that you want to do it when page loads, add this script to your page
<script>
function triggerSuggestionLoading() {
//finds autocomplete input text field
var autocomplete = document.getElementsByClassName('ui-autocomplete-input')[0];
//sets autocomplete query, for example
autocomplete.value="test";
//simulates key press triggering completeMethod to be executed
autocomplete.dispatchEvent(new Event('keydown'));
autocomplete.dispatchEvent(new Event('input'));
autocomplete.dispatchEvent(new Event('keyup'));
//sets focus on autocomplete
autocomplete.dispatchEvent(new Event('focus'));
//clears autocomplete text
autocomplete.value="";
}
window.onload = function() {
triggerSuggestionLoading();
};
</script>
Actually whenever you refresh your suggestion list and want to load suggestions into p:autocomplete just call triggerSuggestionLoading() method at the end (after all procedures are finished).
I've tested it in Chrome and Edge.

Is there any way to stop ajax call when user value is null in input

I am using keyup event for ajax call on input tag and f:validaterequired tag. On every ajax event(Keyup) f:validaterequired is validated. I dont want to validate when value is null. Is there way to do that. I definitely need to use keyup event. I know i can use blur event but requirement need keyup event. Thanks`
<h:inputtext id="id" value="#{bean.somevalue}">
<f:ajax event="keyup" listener="#{bean.listenermethod}" execute="#this
messages" render="#all"
<f:validaterequired/>
</h:inputtext>
` I know we can use delay attribute in ajax to give some time. I dont want to use delay attribute. Currently i am using custom validator in bean to check.
If I understand the problem it works for me to add
onkeyup="if(!$(this).val()) return false;"
to the h:inputText.

Flex/Spark: How much logic in view? How to clear a TextField as a reaction to a user click or an event?

When using Flex with Spark, I have a simple chat window with a TextInput to enter your message and a send Button.
TextInput
Starts out as ""
Should be set to "" last in the function that handles the message sending
Should also be set to "" as a response for event="myOtherEvent"
Button
Should only be enabled when the TextInput's text.length > 0
At first I thought it was pretty clean to skip binding the text being entered into the TextInput to anything in my model and let that logic for button enabling/disabling stay in the view.
I still feel that it's a pretty nice approach except for the fact that it isn't a complete solution as it does not clear the TextInput.text as a response to receiving event="myOtherEvent".
The MXML for that partial solutions is:
<s:TextInput id="chatText" width="100%" height="32" />
<s:Button
label="Send"
enabled="{chatText.text.length > 0}"
click='{model.send(chatText.text); chatText.text=""}'
/>
If it wasn't for my event response requirement, how do you feel about that solution?
There is some logic in the Button, but just basic setting and checking. I know that it's a good idea to separate logic and presentation, but I thought this was a nice balance.
A complete solution I can think of would be to:
Have a two way binding of chatText.text and a property in my model
And in the set method for that property, I would dispatchEvent(new Event("updateButton")
A function in the same model class would bind to that event. That function would also be read in enabled="{model.thatFunction()}" of the Button. The function would return chatTextStringPropertyInModel.length > 0 and thus (by jumping through some hoops) would see to that the send-Button is enabled when there is text available for sending.
The model.send(chatText.text) can set chatTextStringPropertyInModel="" after sending and as that property is two-way bound with chatText.text the change would be reflected in the UI too.
My questions:
How much logic is all right to have in the view?
How should I solve this? What is most elegant and maintainable?
Maybe I'm confused but I don't see an issue in your solution. You just need to add an event handler for your other event
<fx:Script>
<![CDATA[
//clear text and disable button on other event
private function onMyOtherEvent(event:Event):void
{
chatText.text = "";
}
]]>
</fx:Script>
<s:TextInput id="chatText" width="100%" height="32" />
<s:Button
label="Send"
enabled="{chatText.text.length > 0}"
click='{model.send(chatText.text); chatText.text=""}'/>
Also I don't think there's anything wrong with a view component handling it's own view logic...

JQuery Validation Engine, doesn't live validate if i add a element after page was loaded?

at the moment i'm using this validation plugin: (http://www.position-absolute.com/articles/jquery-form-validator-because-form-validation-is-a-mess/)
but when it comes to the part of validating i have a problem.
If i want to be able to validate a element which doesn't exist from the beginning, it only validates it when i press submit. But i want to be able that the element gets a validation while especially the focus get lost. on a element which is there all the time i can type, focus lost, and it writes "something wrong" and disapear if i changed the value to anything correct. but if i do the same thing on a element which i added with the jquery append function, it won't do anything until i press submit.
anyone a simple solution for this. perhaps with the jquery .live function?
this is my script:
var use_ajax=true;
$.validationEngine.settings={};
$("#contact-form").validationEngine({
inlineValidation: true,
promptPosition: "centerRight",
success : function(){use_ajax=true},
failure : function(){use_ajax=false;}
})
and this is a sample of an element which get added by append:
<tr>
<td><label for="email">Nummer</label></td>
<td><input type="text" value="" id="nummer" name="nummer" class="validate[required]"></td>
<td> </td>
</tr>
The accepted answer i had first, won't work with this:
$("#contact-form").validationEngine({
ajaxSubmit: true,
ajaxSubmitFile: "submit.php",
ajaxSubmitMessage: "Contact saved succesful! <br> <img src=''/> <a href='test.php'>TestLink</a>",
ajaxSubmitExtraData: "contact=john",
success : false,
failure : function() {}
});
This is normal.
When you bind the validation to your inputs, bindings for focus, blur etc are bound to the inputs. when you add an input item, they are not bound.
To bind them to, call the validation binding again after you added new inputs.
It might be so that the elements that were bound, will get second bindings, so you might have to unbind the validator:
$.removeData($('#my_form_id'),'validator');
and then bind it again
$('#my_form_id').validate()
#Edit to release any binds on an object, you can do .unbind() this is for events tough. I think jqtransform works on a class selector ? like class="jqtransform", you can try to remove that class