I'm providing a button to add new inputText inside a cellEditor in a dataTable.
I would like to set focus on this new inputText automatically (after clicking the button) such that the user may begin entering data without having to first click on the cell.
My code looks like this:
<p:commandButton action="#{myBean.addNewKeyword}" oncomplete="setFocus();" value="New keyword" onclick="editKeywords();" update='keywordForm' icon="fa fa-plus" />
<p:dataTable id="editKeywordsTbl" value="#{myBean.currentListKeywords}" var="keyWd" editMode="cell" editable="true" resizableColumns="true" widgetVar="editKeywords" rowIndexVar="index" >
<p:ajax event="cellEdit" listener="#{myBean.onCellEditKeywords}" update="form" />
<p:column headerText="Keyword" width="80">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{keyWd.keyword}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{keyWd.keyword}" placeholder="click here to edit" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
I tried to set the fokus on the last inputText with javascript:
function setFocus() {
var myTable = document.getElementById('editKeywordsTbl');
var inputs = myTable.getElementsByTagName('input');
var elemLast = inputs[inputs.length - 1];
elemLast.focus();
};
Unfortunately this's not working!
I should maybe mention, that this is happening inside a dialog.
Any help is highly appreciated. Thanks
For clarification: My problem is not getting the id of the inputText.
With my Javascript, I have access to this element and so I can get the id.
Edit:
I tried elemLast.click();
in my javascript. The new inputText is open for edit and has focus for a second and then get lost.
I don't understand why is this happening.
Edit2 - Minimal reproducible example:
The Xhtml page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
Hello from Facelets
<br />
<script type="text/javascript">
function setFocus() {
$(document).ready(function () {
var myTable = document.getElementById('editKeywordsTbl');
var inputs = myTable.getElementsByTagName('input');
var elemLast = inputs[inputs.length - 1];
console.log("elemLast: " + elemLast.id);
elemLast.click();
elemLast.focus();
});
}
</script>
<h:form id="keywordForm" prependId="false" >
<p:commandButton action="#{myBean.addNewKeyword}" oncomplete="setFocus();" value="New keyword" update='keywordForm' />
<br /><br /><br/>
<p:dataTable id="editKeywordsTbl" value="#{myBean.currentListKeywords}" var="keyWd" editMode="cell" editable="true" resizableColumns="true" widgetVar="editKeywords" rowIndexVar="index" >
<p:ajax event="cellEdit" listener="#{myBean.onCellEditKeywords}" />
<p:column headerText="Keyword" width="80">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="[click me to edit]" rendered="#{keyWd.name == ''}" />
<h:outputText value="#{keyWd.name}" rendered="#{keyWd.name != ''}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{keyWd.name}" required="true" requiredMessage="Enter a keyword!" placeholder="click here to edit" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
Backing bean:
package test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import org.primefaces.event.CellEditEvent;
import test.entity.Keyword;
@Named
@SessionScoped
public class MyBean implements Serializable {
private List<Keyword> currentListKeywords = new ArrayList<>();
public void addNewKeyword() {
Keyword ap = new Keyword();
ap.setName("");
currentListKeywords.add(ap);
}
public void onCellEditKeywords(CellEditEvent event) {
Object newWord = event.getNewValue();
// LOG.info("newWord: " + newWord);
FacesContext context = FacesContext.getCurrentInstance();
Keyword currentWord = context.getApplication().evaluateExpressionGet(context, "#{keyWd}", Keyword.class);
if (newWord == null) {
newWord = " ";
}
if (currentWord != null) {
currentWord.setName((String) newWord);
}
// ejbFacade.editKeyword(currentWord);
}
public List<Keyword> getCurrentListKeywords() {
return currentListKeywords;
}
public void setCurrentListKeywords(List<Keyword> currentListKeywords) {
this.currentListKeywords = currentListKeywords;
}
}
Finally the Keyword class:
package test.entity;
import java.io.Serializable;
public class Keyword implements Serializable {
private String name;
public Keyword(String name) {
this.name = name;
}
public Keyword() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Yes, I managed to solve this issue. Moving the addNewKeyword
button in a separate form and removing required
and requiredMessage
attribute from the inputText solved the problem. I don't know why!?
<h:form >
<p:commandButton action="#{myBean.addNewKeyword}" oncomplete="setFocus();" value="New keyword" update='keywordForm' />
<br /><br /><br/>
</h:form>
<h:form id="keywordForm" prependId="false" >
<p:dataTable id="editKeywordsTbl" value="#{myBean.currentListKeywords}" var="keyWd" editMode="cell" editable="true" resizableColumns="true" widgetVar="editKeywords" rowIndexVar="index" >
<p:ajax event="cellEdit" listener="#{myBean.onCellEditKeywords}" />
<p:column headerText="Keyword" width="80">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="[click me to edit]" rendered="#{keyWd.name == ''}" />
<h:outputText value="#{keyWd.name}" rendered="#{keyWd.name != ''}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{keyWd.name}" placeholder="click here to edit" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</h:form>
Thanks to everybody for the contribution.