Primefaces onkeyPress triggerevent - jsf

I'm doing Primefaces 5.1. In my page use two commandButton Add,Edit button and username Text field. When I press enter in username text field script to perform editbutton click want perform.But it will perform addButton click.I try below code:
<h:head>
<script>
function callEvent(evnt)
{
if(event.keyCode==13)
{
$('editbutton').trigger('click');
}
</script>
</h:head>
<h:form>
<p:inputText id="userNameField" onkeyPress="callerEvent(event)"/>
.....
....
<p:commandButton id="addButton" value="Save" action="#{user.saveButton}"/>
<p:commandButton id="editbutton" value="Edit" action="#{user.editButton}"/>
</h:form>
When I press enter in textfield it will not perform editbutton only trigger with first button that is addbutton.If I change position of button i.e editbutton is first it will perform editbutton.

You can try with:
<h:form id="user-form">
and:
<script>
function callEvent(event) {
if(event.keyCode==13) {
$('#user-form\\:editbutton').click();
return false;
}
</script>
See also:
Default action to execute when pressing enter in a form

There are two issues in your code:
1. function name is callEvent, but you are using callerEvent with text field keyPress event.
2. id selector for editbutton is not correct to get element.
You can simply do it with jQuery like selector (ends-with) as following:
<p:inputText id="userNameField" />
$("input[id$='userNameField']").on('keypress', function(event) {
var keycode = event.keyCode ? event.keyCode : event.which;
if(keycode == '13')
$("input[id$='editbutton']").get(0).click();
});

Related

Primefaces selectOneMenu focus not working

I am using PrimeFaces 5.1 in my application,I used selectOneMenu inside of dataTable, When I press on add more button to need to focus selectOneMenu button.
Sample Code
JavaScript
function focusMenu(id)
{
var focusId="#{p:component('mainTable')}"+":"+id;
PrimeFaces.focus(final);
}
xhtml
<div style="padding-left:4px;height:
expression(this.scrollHeight > 399? '400px' : 'auto');max-height:400px;overflow-x:auto;overflow-y:auto;">
<p:dataTable id="mainTable" value=#{main.UserDataTable} .....>
<p:column headerText="Drop Down">
<p:selectOneMenu id="dropdDownId"...>
.....
</p:selectOneMenu>
</p:column>
<p:column headerText="Operation">
<p:commandButton value="Add More Row" action="{user.addMoreRowAction}"
update="mainTable"/>
</p:column>
</p:dataTable>
</div>
Java
public String addMoreRowAction()
{
RequestContext.getCurrentInstance().execute("focusMenu('"+ rowIndex + ":dropdDownId"')");
return null;
}
Here the above code is work fine to focus the last added selectOneMenu as what I expected, but the browser scroll bar is not move down based on focusing the recently added selectOneMenu component.
Please help me to solve the issue.
You can take the scrollbar to the focus id using scrollTop function.
Pass the focusid into the function.
function setScrollPos(focusId){
$('html,body').animate({
scrollTop: $(focusId).offset().top-65
}, 1000);
}
Call the above function
function focusMenu(id)
{
var focusId="#{p:component('mainTable')}"+":"+id;
PrimeFaces.focus(final);
setScrollPos(focusId); <<------
}

How do I invoke managed bean from an ICEfaces modal popup?

I am using Eclipse Luna EE, Tomcat v7.0 and ICEFaces 3.2
I have a form for label printing that the user enters information such as item number, item name and label type. The user then submits the form. This sends the information to a label printer, in a ZPL string, which then prints out the correct label for the item. This all works no problem.
The form makes a check against the print quantity, in case of a high value (100+ in production). If the print quantity is over a certain value (> 2. purely for testing purposes) then the "testFlag" boolean is set to true, the modal box is displayed and an error flag is set so that the print command doesn't execute.
The modal box asks if the user entered the correct quantity, with Yes/No buttons available.
The printUI and the modal popup are inside the same <ice:form> element, with the popup box rendered and visible if the testFlag is set to true.
The Problem:
When I click the "Yes" button in the modal box, it doesn't carry out the action I have assigned to it (System.out.println("Yes Button!")). The modal box closes and nothing happens.
I can then resubmit the form and the modal box appears again, then I click "Yes" and nothing happens.
If I change the quantity to 2 and submit, then it executes the print command no problem.
I am guessing that it is a problem with the way the session is being handled.
Question:
How do I get the "Yes" button on the modal box to carry out the code I am wanting?
I've tried:
Using <ice:commandLink>, <h:button>, <h:commandButton>, <h:commandLink>
Having the modal popup and the form in separate <ice:form> tags (This refreshed the session and removed all entered data).
Using an actionListener
code containing the form:
<h:body>
<div id="surround">
<ice:form id="test" prependId="false">
<ui:include src="./printUI.xhtml" />
<ui:include src="./printQtyPopup.xhtml" />
</ice:form>
</div>
</h:body>
printQtyPopup.xhtml
<ui:composition>
<ice:panelPopup modal="true" visible="#{validateBean.testFlag}" rendered="#{validateBean.testFlag}">
<f:facet name="header">
<ice:outputText value="Print Quantity Check" />
</f:facet>
<f:facet name="body">
<ice:panelGrid>
<ice:outputText value="You selected a print quantity of: #{validateBean.printAmount}" />
<ice:outputText value="Is this correct?" />
<ice:panelGroup>
<ice:commandButton value="No" />
<ice:commandButton value="Yes" action="#{validateBean.checkQtyYes}" />
</ice:panelGroup>
</ice:panelGrid>
</f:facet>
</ice:panelPopup>
</ui:composition>
Relevant ValidateBean.java code
public void validate() { //validation checks are carried out when the user clicks "Print" on the printUI.
if (!errorFlag && checkQty && printQty > 2) {
testFlag = true;
errorFlag = true;
System.out.println("Qty Check Modal");
}
if (!errorFlag) {
if (printQty > 0) {
initialiseString();
initialisePrinter();
clear();
} else {
printQty = 0;
errorMessage = true;
quantityInvalid = true;
errorFlag = true;
}
}
}
public void checkQtyYes() {
System.out.println("Yes Button!");
}
I found an alternative.
I have removed the modal popup and any code linked with it.
I have added in a <ice:panelConfirmation> at the end of my form. This is only rendered if the print quantity is above whatever number I set.
I get the number by using a valueChangeListener="#{validateBean.printQtyChange}" on my Print Quantity <h:inputText> with onblur="submit()"
I tried the onchange="submit()" but ran into problems when submitting a string of print jobs. I would have to press "ENTER" to force the onchange attribute to activate, which I have been assured the users don't want.
The <ice:panelConfirmation> works by pausing the submit of the form and waits for a response before it either continues or stops the submit. Which accomplishes what I was trying to achieve with the modal popup.
Print Quantity Input Text:
<h:inputText id="printQty" value="#{validateBean.printAmount}" size="8" autocomplete="off"
maxlength="3" required="true" onblur="submit()"
valueChangeListener="#{validateBean.printQtyChange}" />
valueChangeListener:
public void printQtyChange(ValueChangeEvent e) {
printAmount = e.getNewValue().toString();
try {
ls.setPrintQty(Integer.parseInt(printAmount));
} catch (NumberFormatException eve) {
errorMessage = true;
quantityInvalid = true;
errorFlag = true;
}
printQty = ls.getPrintQty();
System.out.println("Qty : " +printQty);
if (printQty < 1) {
errorMessage = true;
quantityInvalid = true;
errorFlag = true;
}
}
Panel Confirmation: inside the <ice:form>. Just before the closing of the form
<ice:panelConfirmation id="confirmQty"
acceptLabel="Yes"
cancelLabel="No"
message="Your entered the quantity: #{validateBean.printQty}. Is this correct?"
title="Confirm Quantity"
draggable="false"
rendered="#{validateBean.printQty > 2}" />
Print Button: tied in with the <ice:panelConfirmation>
<ice:commandButton styleClass="button" id="printButton" value="Print"
actionListener="#{validateBean.validate}" panelConfirmation="confirmQty" />
If anyone does know of a way to invoke a managed bean from a conditional ICEfaces modal popup that would be great also.
UPDATE
I've since changed all my <h:inputText> to <ice:inputText> and added the partialsubmit="true" to my input field for the quantity. with adding this I have been able to remove the onblur="submit()"
NEW Print Quantity Input Text:
<ice:inputText id="printQty" value="#{validateBean.printAmount}" size="8" autocomplete="off"
maxlength="3" required="true" valueChangeListener="#{validateBean.printQtyChange}"
partialSubmit="true" />
This has removed the issue where sometimes it still had problems when submitting a string of jobs.
I haven't put partialsubmit="true" on the <ice:form> because I had to then declare every other input field as partialsubmit="false" to prevent unnecessary code being executed. It's tidier to only have it on the input field I want to check.

Problems with JSF datatable and Bootsfaces modal windows

I am using JSF for my webapp (combined with EJB) and Bootsfaces as JavaScript addition to show modal windows. I am having a list of items that are being shown through a dataTable. And by clicking on a command button inside my list I am opening a modal window, asking the user "wether he is sure he wants to delete". That modal confirm dialog has YES and NO. I can execute the yes execute button inside the modal window. But I cant do #{controller.delete(item)} because the item is only server side available while building the list table. Somehow I have to send the actual selected item to the modal window to set it somehow in that controller call...???
Anyone got an idea?
<!-- looping the jsf list //-->
<h:dataTable value="#{controller.itemlist}" var="item"...
...
<!-- showing modal window //-->
<h:commandButton value="delete" action="" onClick="return false;" p:toggle-data.... />
</h:dataTable>
</h:form>
...
<!-- modal window in panel, with item not set //-->
...
<h:commandButton action="#{controller.delete(item)}" />
</h:form>
</b:panel>
...
You could use ajax to populate your modal's content :
$.ajax({
url : "yourPage.jsf",
type : "POST",
data : {
id: "your object's id"
},
dataType : "html"
}).done(function(html) {
$("#yourModal").html(html);
});
This ajax should be called with onclick event on your <h:commandButton>
And of course, you'd need to create a JSF view for your modal content. This view will contain your text and your two buttons "Yes" and "No". "No" should just dismiss your modal, while "Yes" should call your bean action : <h:commandButton action="#{controller.delete(item)}" />.
Don't forget to populate your controller item with the id parameter to bind data to your view.
EDIT :
I'll try to show you an example.
Main View (view.xhtml) :
<h:form>
<h:dataTable value="#{controller.itemlist}" var="item">
<h:column>
...
</h:column>
<h:column>
<h:commandButton value="delete" onclick="return populateModal(#{item.id}); " />
</h:column>
</h:dataTable>
</h:form>
Script to populate your modal (view.xhtml) :
<script type="text/javascript">
function populateModal(id) {
$.ajax({
url: "view2.jsf",
type: "POST",
data: { id: id },
dataType: "html"
}).done(function(html) {
$("#modal").html(html);
$("#modal").show();
});
return false;
}
</script>
Then you need a view for your modal's content (view2.xhtml) :
<h:form>
Delete #{testBean2.item.name} ?
<h:commandButton value="YES" action="#{testBean2.delete(testBean2.item)}" />
<h:commandButton value="NO" onclick="return closeModal();" />
</h:form>
And a controller for this view (testBean2.java) :
private Item item;
#PostConstruct
public void init() {
// GET id parameter from HTTPRequest
// Populate Local Item
}
public void delete(Item item) {
// Delete your item
}

Cannot show dialog in Primefaces RequestContext.execute() call

I have a tabview in which I want to refresh contents of one specific tab whenever user selects that tab. I also want modal dialog to pop up while tab is being refreshed.
Here is tabView with tabChange ajax event handler
<p:dialog widgetVar="statusDialog" modal="true" draggable="false" minimizable="false" appendToBody="true" closable="false" header="Processing..." resizable="false" maximizable="false">
<p:graphicImage library="assets" name="ajax-loader.gif"></p:graphicImage>
</p:dialog>
<p:tabView id="tabview" orientation="top" dynamic="false">
<p:ajax event="tabChange" listener="#{bean.tabChangeListener}"></p:ajax>
<p:tab title="tab1">
<ui:include src="/WEB-INF/views/tab1.xhtml"/>
</p:tab>
<p:tab title="tab2">
<p:remoteCommand actionListener="#{bean.refreshData}" update="someTab2ElementID" name="refresh" global="true" onstart="statusDialog.show()" oncomplete="statusDialog.hide()"/>
<ui:include src="/WEB-INF/views/tab2.xhtml"/>
</p:tab>
</p:tabView>
Here is tabChangeListener:
public void tabChangeListener(TabChangeEvent event) {
if ( event.getTab().getId().equalsIgnoreCase("tab2") ) {
RequestContext.getCurrentInstance().execute("refresh()");
}
}
The refresh remoteCommand is being called as expected, but my statusDialog is never shown. If the same remoteCommand is triggered by a button click the statusDialog appears. There are no errors in JavaScript console.
Why is statusDialog not shown when remoteCommand is triggered by RequestContext.execute() and how can I make it appear? I even tried adding statusDialog.show() to execute() but it didnt help.
I figured it out. Here is the solution:
<h:outputScript>
var blockCount=0;
function showStatus() {
if (blockCount==0) statusDialog.show();
blockCount++;
};
function hideStatus() {
blockCount--;
if (blockCount==0) statusDialog.hide();
};
</h:outputScript>
<p:ajaxStatus onstart="showStatus();" onsuccess="hideStatus();" onerror="blockCount=0;statusDialog.hide();errorDialog.show();"/>
<p:remoteCommand actionListener="#{bean.refreshData}" update="someTab2ElementID" name="refresh" global="true" onstart="showStatus()" oncomplete="hideStatus()"/>
Apparently the reason why my status dialog was not being shown is that another Ajax call finished and called statusDialog.hide() while my refresh() thing was going on. The JS code above maintains a counter of how many Ajax calls are in progress, and will only hide the status dialog when all calls have finished. Works as intended now!
If you want to show dialog when a specific tab is changed, you can inform a js function about, the tab selected control that it is 2 or not by adding a callback parameter via ajax response:
public void tabChangeListener(TabChangeEvent event) {
if ( event.getTab().getId().equalsIgnoreCase("tab2") ) {
RequestContext.getCurrentInstance().addCallbackParam("index", 2);
}
}
And use:
<p:ajax event="tabChange" listener="#{bean.tabChangeListener}"
oncomplete="showOrNot(xhr,status,args)"></p:ajax>
This will call the js function and it's going to control that the changed tab is 2 or not:
function showOrNot(xhr,status,args) {
if(args.index==2) {
statusDialog.show();
}
}
Or different approach is defining a value and using visible property of the p:dialog:
public void tabChangeListener(TabChangeEvent event) {
if ( event.getTab().getId().equalsIgnoreCase("tab2") ) {
this.condition=true;
}
}
And <p:dialog visible="#{bean.condition}"/>. And maybe you need to focus on your first approach and you can give an ID to p:dialog and update it via p:remoteCommand:
<p:remoteCommand actionListener="#{bean.refreshData}" update="someTab2ElementID dialog" name="refresh" global="true" onstart="statusDialog.show()" oncomplete="statusDialog.hide()"/>
Don't forget to give the exact client ID of the dialog in the update property of p:remoteCommand.

Jsf calling bean method from input text when pressing enter

JSF 2.0, Mojarra 2.0.1, PrimeFaces 3.4.1
Here is a p:inputText component which is expected to call a backing bean method when the enter key is pressed.
<p:inputText id="commentInput" rendered="#{status.haveComment}"
value="#{statusBean.newComment}"
onkeypress="if (event.keyCode == 13) { onchange(); return false; }">
<f:ajax event="change" listener="#{statusBean.test}" />
</p:inputText>
While backing bean has the method of:
public void test(AjaxBehaviorEvent event) {
System.out.println("Pressed enter!");
}
It's calling method when enter key is pressed but it has more than this; unexpected behaviour case:
--Click input text
----Type some letters
------Click somewhere else in the page
--------CONSOLE: Pressed enter!
I think ajax event=change detects a change somehow and calls the method. How to convert this p:inputText component into a proper comment taker component like Facebook or others has?
This is the way how onchange event works in HTML. It is happening when text in input element is changed, but is fired when component loses focus (in your case that is the moment when you click somewhere else in the page).
You can define p:remoteCommand for test method and just write:
<p:remoteCommand name="test" actionListener="#{statusBean.test}"/>
<p:inputText id="commentInput" rendered="#{status.haveComment}"
value="#{statusBean.newComment}"
onkeypress="if (event.keyCode == 13) { test(); return false; }"/>
and in backing bean:
public void test() {
System.out.println("Pressed enter!");
}
With newer PrimeFaces versions (5+ at least) you can use p:defaultCommand instead of scripting. Though you can't use p:remoteCommand then, because p:defaultCommand needs something clickable.
<p:inputText id="input" />
<p:defaultCommand target="submit" />
<!--you can show the button to allow the user to click too, or hide it with display: none-->
<p:commandButton id="submit" style="display: none;" process="input" />
By default p:defaultCommand applies to the whole form. You could limit it with the scope attribute.

Resources