开发者

a4j:jsFunction with actionListener inside of h:dataTable

I'm having problem with using a4j:jsFunction with actionListener inside of h:dataTable, when I want to invoke an action over particular row with a4j:commandLink it works flawless but when I want to invoke the action with a4j:jsFunction & actionListener it's always invoked over the last element in dataTable Let me give you an example:

    <a4j:form aj开发者_StackOverflow中文版axSubmit="true" reRender="mainForm" id="mainForm">
        <a4j:region>
            <t:saveState value="#{ts.list}" />
        </a4j:region>

        <h:dataTable value="#{ts.list}" var="el" binding="#{ts.bind}">
        <h:column>#{el}</h:column>>
        <h:column>
            <a4j:commandLink actionListener="#{ts.rem}">
                    <h:outputText value="delete by CMDLink" />
                </a4j:commandLink>
            </h:column>
        <h:column>
                <a href="#" onclick="okClicked();">delete by okClicked</a>
                <a4j:jsFunction name="okClicked"
                    actionListener="#{ts.rem}"
                />
        </h:column>
   </h:dataTable>
    </a4j:form>

now, the bean's code:

package com.sth;

import java.util.ArrayList;
import java.util.List;

import javax.faces.component.UIData;
import javax.faces.event.ActionEvent;

public class Ts {

    private List<String> list = new ArrayList<String>();
    private UIData bind;

    public Ts(){
        list.add("element1");
        list.add("element2");
        list.add("element3");
        list.add("element4");
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void rem(ActionEvent ae) {
        String toRem = (String) bind.getRowData();
        System.out.println("Deleting " + toRem);
        list.remove(toRem);
    }

    public UIData getBind() {
        return bind;
    }

    public void setBind(UIData bind) {
        this.bind = bind;
    }

}

when I use a4j:commandLink to remove element, it works as its expected, but when I use a4j:jsFunction to invoke actionListener it invokes action against last element :( Any ideas? Cheers


you can achive your goal by moving <a4j:jsFunction> out from <h:datatable> control

This is an example

 <a4j:form ajaxSubmit="true" reRender="mainForm" id="mainForm">

    <h:dataTable value="#{ts.list}" var="el" binding="#{ts.bind}">
      <h:column>#{el}</h:column>>
      <h:column>
            <a4j:commandButton 
                onclick="#{rich:component
                     ('confirmation')}.show();return false">Delete</a4j:commandButton>
      </h:column>
    </h:dataTable>
    <a4j:jsFunction name="remove" action="#{ts.remove(el)}" reRender="mainForm"/>
 </a4j:form>

Confirmation dialog:

<rich:modalPanel id="confirmation" width="250" height="150">
        <f:facet name="header">
            <h:panelGrid columns="2">
                <h:graphicImage value="/img/delete.gif"/>
                <h:outputText value="Confirmation"/>
            </h:panelGrid>
        </f:facet>
        <h:panelGrid style="height: 100%">
            <h:panelGrid columns="2" cellpadding="5px">
                <h:graphicImage value="/img/error_large.gif"/>
                <h:outputText value="Delete ?" style="font-size: large;"/>
            </h:panelGrid>
            <h:panelGroup style="margin-top: 20px">
                <input type="button" value="Yes" style="width: 100px"
                       onclick="#{rich:component('confirmation')}.hide();remove();return false"/>
                <input type="button" value="No" style="width: 100px"
                       onclick="#{rich:component('confirmation')}.hide();return false"/>
            </h:panelGroup>
        </h:panelGrid>
    </rich:modalPanel>


As per the comments it turns out that you just want to fire a confirmation dialogue. You can also use a4j:commandLink for this, call it in the onclick attribute and let it return either true or false to either allow or block the action. Here's a kickoff example as you would do with a standard confirmation dialog:

<a4j:commandLink onclick="return confirm('Are you sure?');">

This way you don't need to struggle/debug the weird a4j:jsFunction behaviour for hours.


It is my understanding that with the a4j:jsFunction tag:

<a4j:jsFunction name="okClicked" actionListener="#{ts.rem}" />

being placed within a column of a datatable, a JavaScript function called okClicked would be added to the HTML page in the column for each row of the table. Having the same name, each JavaScript function would overwrite the definition of the previous one, so that when okClicked() is called, only the last defined function is actually executed. This would be why the actionListener is being invoked that invokes the "action against last element".

A way around this would be to include the row index as part of the name of the JavaScript function being created by the a4j:jsFunction tag:

<h:dataTable value="#{ts.list}" var="el" binding="#{ts.bind}" rowIndexVar="index">
    <h:column>
        <a href="#" onclick="okClicked#{index}();">delete by okClicked</a>
        <a4j:jsFunction name="okClicked#{index}" actionListener="#{ts.rem}"/>
    </h:column>
</h:datatable>

I've not tested the above solution (and I don't know whether there would be an issue binding #{ts.rem} to a JS function actionListener rather than binding it to a commandLink actionListener) but if the onClick value of okClicked#{index}(); doesn't work directly, then instead call a javaScript function that creates the function name from a string built from the index value:

function onClicked(row) {
    functionStr = "okClicked" + row;
    window[functionStr]();
}

I've had to use something similar requiring a grid of 'jsFunction's within a datatable where I had multiple columns to deal with as well as multiple rows.

Hope this is useful for others in the future.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜