как я могу передать выбранную строку в commandlink внутри datatable или ui: repeat?

<p>я использую primefaces в приложении jsf 2. у меня есть <code><p:datatable></code>, и вместо того, чтобы выбирать строки, я хочу, чтобы пользователь мог напрямую выполнять различные действия над отдельными строками. для этого у меня есть несколько <code><p:commandlink></code>s в последнем столбце.</p><p>моя проблема: как я могу передать идентификатор строки в действие, запущенное по командной ссылке, чтобы я знал, на какую строку действовать? я пытался использовать <code><f:attribute></code>:</p><pre><code><p:datatable value="#{bean.items}" var="item"> ... <p:column> <p:commandlink actionlistener="#{bean.insert}" value="insert"> <f:attribute name="id" value="#{item.id}" /> </p:commandlink> </p:column> </p:datatable> </code></pre><p>но это всегда дает 0 - очевидно, переменная строки <code>f</code> недоступна при визуализации атрибута (она работает, когда я использую фиксированное значение).</p><p>у кого-нибудь есть альтернативное решение?</p>

<p>что касается причины, <code><f:attribute></code> специфичен для самого компонента (заполняется во время построения представления), а не для повторяющейся строки (заполняется во время визуализации представления).</p><p>есть несколько способов достижения этого требования.</p><ol> <li> <p>вместо этого используйте <a href="http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/f/param.html"><code><f:param></code></a> . добавляет параметр запроса.</p> <pre><code><h:commandlink action="#{bean.insert}" value="insert"> <f:param name="id" value="#{item.id}" /> </h:commandlink> </code></pre> <p>если ваш бин имеет область запроса, пусть jsf установит его с помощью <a href="http://download.oracle.com/javaee/6/api/javax/faces/bean/managedproperty.html"><code>@managedproperty</code></a> </p> <pre><code>@managedproperty(value="#{param.id}") private long id; // +setter </code></pre> <p>или, если ваш компонент имеет более широкую область действия или если вы хотите более детальную проверку/преобразование, используйте <a href="http://download.oracle.com/javaee/6/javaserverfaces/2.1/docs/vdldocs/facelets/f/viewparam.html"><code><f:viewparam></code></a> в целевом представлении, см. также <a href="https://stackoverflow.com/questions/4888942/viewparam-vs-managedpropertyvalue-param-id">f: viewparam vs @managedproperty</a> :</p> <pre><code><f:viewparam name="id" value="#{bean.id}" required="true" /> </code></pre> <p>в любом случае, это имеет преимущество в том, что модель данных не обязательно должна быть сохранена для отправки формы (для случая, когда ваш компонент имеет область действия запроса).</p> <hr></li> <li> <p>вместо этого используйте <a href="http://download.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/f/setpropertyactionlistener.html"><code><f:setpropertyactionlistener></code></a> . преимущество состоит в том, что это устраняет необходимость доступа к карте параметров запроса, когда боб имеет более широкую область действия, чем область запроса.</p> <pre><code><h:commandlink action="#{bean.insert}" value="insert"> <f:setpropertyactionlistener target="#{bean.id}" value="#{item.id}" /> </h:commandlink> </code></pre> <p>в комбинации с</p> <pre><code>private long id; // +setter </code></pre> <p>он будет доступен только по свойству <code>id</code> в методе действия. это только требует, чтобы модель данных была сохранена для запроса отправки формы. лучше всего поместить бин в область видимости с помощью <code>@viewscoped</code>.</p> <hr></li> <li> <p>если ваш servletcontainer поддерживает servlet 3.0/el 2.2, просто передайте его как аргумент метода. это также требует, чтобы модель данных была сохранена для запроса отправки формы. лучше всего поместить бин в область видимости с помощью <code>@viewscoped</code>.</p> <pre><code><h:commandlink action="#{bean.insert(item.id)}" value="insert" /> </code></pre> <p>в комбинации с:</p> <pre><code>public void insert(long id) { // ... } </code></pre> <p>вы даже можете передать весь объект предмета:</p> <pre><code><h:commandlink action="#{bean.insert(item)}" value="insert" /> </code></pre> <p>с:</p> <pre><code>public void insert(item item) { // ... } </code></pre> <p>в контейнерах servlet 2.5 это также возможно, если вы предоставите реализацию el, которая поддерживает это, например, jboss el. подробнее о конфигурации см. <a href="https://stackoverflow.com/questions/3284236/jsf-2-0-method-invocation/3284328#3284328">этот ответ</a> .</p> <hr></li> <li> <p>привязать значение данных к <a href="http://download.oracle.com/javaee/6/api/javax/faces/model/datamodel.html"><code>datamodel<e></code></a> вместо этого, что, в свою очередь, оборачивает элементы.</p> <pre><code><h:datatable value="#{bean.model}" var="item"> </code></pre> <p>с</p> <pre><code>private transient datamodel<item> model; public datamodel<item> getmodel() { if (model == null) { model = new listdatamodel<item>(items); } return model; } </code></pre> <p><em> (делать его <code>transient</code> и лениво создавать его экземпляр в геттере обязательно, если вы используете его в bean-объекте представления или сеанса, поскольку <code>datamodel</code> не реализует <code>serializable</code>) </em></p> <p>тогда вы сможете получить доступ к текущей строке с помощью <a href="http://download.oracle.com/javaee/6/api/javax/faces/model/datamodel.html#getrowdata()"><code>datamodel#getrowdata()</code></a> , ничего не передавая (jsf определяет строку на основе имени параметра запроса по нажатой ссылке/кнопке команды).</p> <pre><code>public void insert() { item item = model.getrowdata(); long id = item.getid(); // ... } </code></pre> <p>это также требует, чтобы модель данных была сохранена для запроса отправки формы. лучше всего поместить бин в область видимости с помощью <code>@viewscoped</code>.</p> <hr></li> <li> <p>вы можете использовать <a href="http://docs.oracle.com/javaee/6/api/javax/faces/application/application.html#evaluateexpressionget%28javax.faces.context.facescontext,%20java.lang.string,%20java.lang.class%29"><code>application#evaluateexpressionget()</code></a> для программной оценки текущего <code>#{item}</code>.</p> <pre><code>public void insert() { facescontext context = facescontext.getcurrentinstance(); item item = context.getapplication().evaluateexpressionget(context, "#{item}", item.class); long id = item.getid(); // ... } </code></pre> <hr></li> </ol><p>какой путь выбрать, зависит от функциональных требований и от того, предлагает ли тот или другой больше преимуществ для других целей. лично я хотел бы продолжить с № 3 или, если вы хотите также поддерживать контейнеры с сервлетом 2.5, с № 2.</p>

<p>в jsf 1.2 это было сделано с помощью <code><f:setpropertyactionlistener></code> (внутри компонента команды). в jsf 2.0 (el 2.2, если быть точным, благодаря balusc) это можно сделать так: <code>action="${filterlist.insert(f.id)}</code></p>

<p>на моей странице просмотра:</p><pre><code><p:datatable ...> <p:column> <p:commandlink actionlistener="#{inquirysocontroller.viewdetail}" process="@this" update=":mainform:dialog\_content" oncomplete="dlg2.show()"> <h:graphicimage library="images" name="view.png"/> <f:param name="trxno" value="#{item.map['trxno']}"/> </p:commandlink> </p:column> </p:datatable> </code></pre><p>боб</p><pre><code> public void viewdetail(actionevent e) { string trxno = getfacescontext().getrequestparametermap().get("trxno"); for (dto item : list) { if (item.get("trxno").tostring().equals(trxno)) { system.out.println(trxno); setselecteditem(item); break; } } } </code></pre>