Add ajax behaviour to JSF renderer

一曲冷凌霜 提交于 2019-12-13 05:26:39

问题


I have a custom JSF component renderer that renders pagination component for datatables, but it hasn't ajax behavior . I learned that it could be done by inserting ajax to encode method or by making support of f ajax tag. Unfortunately I'm not very familiar with ajax, so could you please tell me how I should modify this code to make it ajaxable?

@FacesRenderer(componentFamily="javax.faces.Command",
    rendererType="com.component.Pager")

public class PagerRenderer extends Renderer {

private static final int SHOW_PAGES = 3;
private static final String   HIDDEN_FIELD_ID ="tableFormPaginatorInput";
public void encodeBegin(FacesContext context, UIComponent component)
        throws IOException {
    ClientBehaviorContext behaviorContext =
                            ClientBehaviorContext.createClientBehaviorContext(context,
                           component, "click", component.getClientId(context), null);
    String id = component.getClientId(context);
    UIComponent parent = component;
    while (!(parent instanceof UIForm)) parent = parent.getParent();
    String formId = parent.getClientId(context);


    ResponseWriter writer = context.getResponseWriter();
    writer.startElement("div", component);
    writer.writeAttribute("class", "paginator-section", null);
    String styleClass = (String) component.getAttributes().get("styleClass");
    String selectedStyleClass
            = (String) component.getAttributes().get("selectedStyleClass");
    String dataTableId = (String) component.getAttributes().get("dataTableId");


    // find the component with the given ID

    UIData data = (UIData) component.findComponent(dataTableId);

    int first = data.getFirst();
    int itemcount = data.getRowCount();
    int pagesize = data.getRows();
    if (pagesize <= 0) pagesize = itemcount;

    int pages = itemcount / pagesize;
    if (itemcount % pagesize != 0) pages++;

    int currentPage = first / pagesize;
    if (first >= itemcount - pagesize) currentPage = pages - 1;
    int startPage = 0;
    int endPage = pages;
    if (SHOW_PAGES  > 0) {
        startPage = (currentPage / SHOW_PAGES ) * SHOW_PAGES ;
        endPage = Math.min(startPage + SHOW_PAGES , pages);
    }
    if (currentPage > 0)
        writeLink(writer, component, formId, id, "<", styleClass);

    if (startPage > 0)
        writeLink(writer, component, formId, id, "..", styleClass);

    for (int i = startPage; i < endPage; i++) {
        writeLink(writer, component, formId, id, "" + (i + 1),
                i == currentPage ? selectedStyleClass : styleClass);
    }

    if (endPage < pages)
        writeLink(writer, component, formId, id, "...", styleClass);

    if (first < itemcount - pagesize)
        writeLink(writer, component, formId, id, ">", styleClass);

  /*  CommandButton commandButton = new CommandButton();
    commandButton.setValue(currentPage);
    commandButton.setUpdate("");
    commandButton.setAjax(true);
    commandButton.addActionListener(new MyActionListener());
    commandButton.encodeAll(context);*/


    writer.endElement("div");
    // hidden field to hold result
    writeHiddenField(writer, component, id);
}

private void writeLink(ResponseWriter writer, UIComponent component,
                       String formId, String id, String value, String styleClass)
 throws IOException {
     writer.writeText(" ", null);
     writer.startElement("a", component);
     writer.writeAttribute("href", "#", null);
     writer.writeAttribute("onclick", onclickCode(formId, id, value) , null);
     if (styleClass != null)
         writer.writeAttribute("class", styleClass, "styleClass");
     writer.writeText(value, null);
     writer.endElement("a");


}

private void writeLink1(ResponseWriter writer, UIComponent component,
                       String formId, String id, String value, String styleClass)
        throws IOException {
    writer.writeText(" ", null);
    writer.startElement("a", component);
    writer.writeAttribute("href", "#", null);
    writer.writeAttribute("data-tableFormPaginator", value, null);
    if (styleClass != null)
        writer.writeAttribute("class", styleClass, "styleClass");
    writer.writeText(value, null);
    writer.endElement("a");



}




private String onclickCode(String formId, String id, String value) {
    return new StringBuilder().append("document.forms['")
            .append(formId).append("']['")
            .append(id).append("'].value='").append(value).append("'; document.forms['")
            .append(formId).append("'].submit(); return false;").toString();
}

private String onclickCodewithout(String formId, String id, String value,UIComponent component) {
    return "jsf.ajax.request('" + component.getClientId() +
            "', null, {'render': '" +
            component.getParent().getClientId() + "',"+id+":"+value+" })";

}
private void writeHiddenField(ResponseWriter writer, UIComponent component,
                              String id) throws IOException {
    writer.startElement("input", component);
    writer.writeAttribute("id", HIDDEN_FIELD_ID, null);
    writer.writeAttribute("class", "paginator-input-value", null);
    writer.writeAttribute("type", "hidden", null);
    writer.writeAttribute("name", id, null);
    writer.endElement("input");
}

public void decode(FacesContext context, UIComponent component) {
    String id = component.getClientId(context);
    Map<String, String> parameters
            = context.getExternalContext().getRequestParameterMap();

    String response = (String) parameters.get(id);
    if (response == null || response.equals("")) return;

    String dataTableId = (String) component.getAttributes().get("dataTableId");
    int showpages = SHOW_PAGES ;//toInt(component.getAttributes().get("showpages"));

    UIData data = (UIData) component.findComponent(dataTableId);

    int first = data.getFirst();
    int itemcount = data.getRowCount();
    int pagesize = data.getRows();
    if (pagesize <= 0) pagesize = itemcount;

    if (response.equals("<")) first -= pagesize;
    else if (response.equals(">")) first += pagesize;
    else if (response.equals("..")) first -= pagesize * showpages;
    else if (response.equals("...")) first += pagesize * showpages;
    else {
        int page = Integer.parseInt(response);
        first = (page - 1) * pagesize;
    }
    if (first + pagesize > itemcount) first = itemcount - pagesize;
    if (first < 0) first = 0;
    data.setFirst(first);
}

private static int toInt(Object value) {
    if (value == null) return 0;
    if (value instanceof Number) return ((Number) value).intValue();
    if (value instanceof String) return Integer.parseInt((String) value);
    throw new IllegalArgumentException("Cannot convert " + value);
}

回答1:


f:ajax tag can only be directly nested in an UIComponent which implements the ClientBehaviorHolder interface.

I saw that you try to implement onclick for your table, if you are using Mojarra, then it has utils method that you help you render onclick behavior that will work with f:ajax as well renderSelectOnclick

http://grepcode.com/file/repo1.maven.org/maven2/com.sun.faces/jsf-impl/2.1.19/com/sun/faces/renderkit/RenderKitUtils.java#RenderKitUtils.renderSelectOnclick%28com.sun.faces.renderkit.FacesContext%2Cjavax.faces.component.UIComponent%2Cboolean%29

You can use it inside your encode method



来源:https://stackoverflow.com/questions/17659287/add-ajax-behaviour-to-jsf-renderer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!