无法将焦点设置在 dataTable 中的 p:inputText

Unable to set focus on p:inputText in dataTable

我提供了一个按钮,用于在数据表的 cellEditor 中添加新的 inputText。
我想自动将焦点放在这个新的 inputText 上(单击按钮后),这样用户就可以开始输入数据而不必先单击单元格。

我的代码如下所示:

<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>

我尝试使用 javascript:

在最后一个 inputText 上设置 fokus
function setFocus() {
    var myTable = document.getElementById('editKeywordsTbl');
    var inputs = myTable.getElementsByTagName('input');
    var elemLast = inputs[inputs.length - 1];
    elemLast.focus();
};

很遗憾,这不起作用!
我应该提一下,这是在对话框中发生的。
非常感谢任何帮助。谢谢

澄清一下:我的问题是没有获取 inputText 的 ID。
使用我的 Javascript,我可以访问此元素,因此我可以获得 ID。

编辑:
我在 javascript 中尝试了 elemLast.click();。新的 inputText 已打开以供编辑,并获得焦点一秒钟,然后就迷路了。
我不明白为什么会这样。

Edit2 - 最小可重现示例:
Xhtml 页面:

<!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>

支持 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;
    }
}

最后是关键字 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;
    }
}

您可以使用一些 js 来完成,在您的按钮中添加一个 oncomplete="selectFocus()" 并使用 p:remoteCommand 调用您的 js 代码,如下所示:

 <p:remoteCommand name="selectFocus" oncomplete="dataEditableFocus('dataTableWidgetVar', false);" />

你的js一定是这样的:

dataEditableFocus = function (dataTableWidgetVar, hasRowIndex) {
    var row;
    var tb = $(document.getElementById(PF(dataTableWidgetVar).id));
    var multiple = $(tb).find('tr td.ui-selection-column');
    if ($(multiple).length === 0) {
        if (hasRowIndex) {
            row = $(tb).find('tr td.ui-editable-column:nth-child(2)');
        } else {
            row = $(tb).find('tr td.ui-editable-column:nth-child(1)');
        }
        $(row).last().find('input').click();
    } else {
        if (hasRowIndex) {
            row = $(tb).find('tr td.ui-editable-column:nth-child(3)');
        } else {
            row = $(tb).find('tr td.ui-editable-column:nth-child(2)');
        }
        $(row).last().parent().children().first().click();
        $(row).last().find('input').click();
    }
}

使用此代码,如果您使用 PF('dataTableWidgetVar').addRow() 在数据表中添加一行 focus go on first element in editable datatable(如果你的 table 是 selectionMode="multiple" ,代码有一些更复杂),你可以编辑代码以关注每个元素数据table。如果您的元素具有 RowIndex,请在调用函数中将其传递为真(table 的定向可能会影响代码!)。

是的,我设法解决了这个问题。在单独的表单中移动 addNewKeyword 按钮并从 inputText 中删除 requiredrequiredMessage 属性解决了这个问题。我不知道为什么!?

    <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>

感谢大家的贡献。