用于jQueryUI拖放的JSF自定义组件

时间:2012-07-16 07:36:12

标签: jsf-2 custom-component

我正在学习构建JSF自定义组件,我想我可以尝试构建一个jQuery的Drag& amp; Drop ..所以我阅读了大部分内容并且实际上可以构建一个足够简单的Draggable和Droppable组件,基本上生成适当数量的jQuery js来支持Drag&直到我可以将“draggable”对象和“droppable”容器关联起来并且几乎可以拖拽/放下东西..

这很简单,我的问题是如何获取被删除内容的“数据”,或者如何绑定到jQuery生成的drop事件...我知道它应该很容易,所以如果有人能指出我在正确的方向(文件/代码样本)我非常感谢...

我会像我想的那样粘贴很少的代码......只是这样你就可以看到我做了什么..我可以分享很多东西(真的粘贴的东西不多......)如果有人需要的话......

(正如你所看到的,我可以绑定一个ajax事件..我只是无法弄清楚如何调用它。)。

TIA ..

...成分

@FacesComponent(Draggable.COMPONENT_TYPE)
public class Draggable extends UIComponentBase  {
    public static final String COMPONENT_TYPE = "ar.com.easytech.Draggable";
    public static final String DEFAULT_RENDERER_TYPE = "ar.com.easytech.DraggableRenderer";
    public static final String COMPONENT_FAMILY = "javax.faces.Output";

    public String getFamily() {
        return COMPONENT_FAMILY;
    }

    public String getFor() {
        return (String) getStateHelper().eval(PropertyKeys.forVal);
    }

    ...

    protected enum PropertyKeys {
        forVal("for"), draggableSelector, revert, containTo;
        String c;

        PropertyKeys() {
        }

        PropertyKeys(String c) {
            this.c = c;
        }

        public String toString() {
            return ((this.c != null) ? this.c : super.toString());
        }
    }

    @Override
    public void encodeEnd(FacesContext facesContext) throws IOException {
        ResponseWriter writer = facesContext.getResponseWriter();

        String clientId = getClientId(facesContext);
        UIComponent targetComponent = findComponent(getFor());
        if(targetComponent == null)
            throw new FacesException("Cannot find component \"" + getFor());

        String target = targetComponent.getClientId();

        writer.startElement("script", null);
        writer.writeAttribute("id", clientId + "_s", null);
        writer.writeAttribute("type", "text/javascript", null);
        writer.write("$(function() {");
        writer.write("$( '#" + target.replace(":", "\\\\:") + "').draggable({");
        if (getRevert() != null) writer.write(" revert: '" + getRevert() + "', ");
        if (getContainTo() != null) writer.write(" containment: '" + getContainTo() + "',");
        writer.write("});");

        writer.write("});");
        writer.endElement("script");
    }

}

Droppable.java

@FacesComponent(Droppable.COMPONENT_TYPE)
public class Droppable extends UIComponentBase implements ClientBehaviorHolder {
    public static final String COMPONENT_TYPE = "ar.com.easytech.Droppable";
    public static final String DEFAULT_RENDERER_TYPE = "ar.com.easytech.DroppableRenderer";
    public static final String COMPONENT_FAMILY = "javax.faces.Output";

    private final static String DEFAULT_EVENT = "drop";
    private static final Collection<String> EVENT_NAMES = Collections.unmodifiableCollection(Arrays.asList(DEFAULT_EVENT));

    public String getFamily() {
        return COMPONENT_FAMILY;
    }

    // Property: for
    public String getFor() {
        return (String) getStateHelper().eval(PropertyKeys.forVal);
    }

    ...

    protected enum PropertyKeys {
        forVal("for"), droppableSelector, activeClass, hoverClass, accept, tolerance, source;
        String c;

        PropertyKeys() {
        }

        // Constructor needed by "for" property
        PropertyKeys(String c) {
            this.c = c;
        }

        public String toString() {
            return ((this.c != null) ? this.c : super.toString());
        }
    }

    @Override
    public void queueEvent(FacesEvent event) {
        FacesContext context = FacesContext.getCurrentInstance();

        if (isRequestSource(context)) {
            Map<String, String> params = context.getExternalContext()
                    .getRequestParameterMap();
            String eventName = params.get("javax.faces.behavior.event");
            String clientId = getClientId(context);

            AjaxBehaviorEvent behaviorEvent = (AjaxBehaviorEvent) event;

            if (eventName.equals("drop")) {
                String dragId = params.get(clientId + "_sourceId");
                String dropId = params.get(clientId + "_targetId");
                DragDropEvent dndEvent = null;
                String datasourceId = getSource();

                if (datasourceId != null) {
                    UIData datasource = (UIData) findComponent(datasourceId);
                    String[] idTokens = dragId.split(String
                            .valueOf(UINamingContainer
                                    .getSeparatorChar(context)));
                    int rowIndex = Integer
                            .parseInt(idTokens[idTokens.length - 2]);
                    datasource.setRowIndex(rowIndex);
                    Object data = datasource.getRowData();
                    datasource.setRowIndex(-1);

                    dndEvent = new DragDropEvent(this,
                            behaviorEvent.getBehavior(), dragId, dropId, data);
                } else {
                    dndEvent = new DragDropEvent(this,
                            behaviorEvent.getBehavior(), dragId, dropId);
                }

                super.queueEvent(dndEvent);
            }

        } else {
            super.queueEvent(event);
        }
    }

    @Override
    public Collection<String> getEventNames() {
        return EVENT_NAMES;
    }

    @Override
    public String getDefaultEventName() {
        return DEFAULT_EVENT;
    }

    @Override
    public void decode(FacesContext context) {

         if (context == null ) {
              throw new NullPointerException();
            }

            String clientId = getClientId(context);
            Map<String, String> requestParameterMap = context.getExternalContext().getRequestParameterMap();
            String value = (String) requestParameterMap.get(clientId);
            if (value == null || value.equals("") || !clientId.equals(value))
              return;
            ActionEvent actionEvent = new ActionEvent(this);
            queueEvent(actionEvent);
    }

    @Override
    public void encodeEnd(FacesContext context) throws IOException {

        ClientBehaviorContext behaviorContext =
                  ClientBehaviorContext.createClientBehaviorContext(context,this, DEFAULT_EVENT, getClientId(context), null);

        ResponseWriter writer = context.getResponseWriter();
        String clientId = getClientId(context);
        UIComponent targetComponent = findComponent(getFor());
        if(targetComponent == null)
            throw new FacesException("Cannot find component \"" + getFor());
        String target = targetComponent.getClientId();

        writer.startElement("script", null);
        writer.writeAttribute("id", clientId + "_s", null);
        writer.writeAttribute("type", "text/javascript", null);
        writer.write("$(function() {");
        writer.write("$( '#" + target.replace(":", "\\\\:") + "').droppable({");

        if (getActiveClass() != null) writer.write(" activeClass: '" + getActiveClass() + "',");
        if (getHoverClass() != null) writer.write(" hoverClass: '" + getHoverClass() + "',");
        if (getAccept() != null) writer.write(" accept: '" + getAccept() + "',");
        if (getTolerance() != null) writer.write(" tolerance: '" + getTolerance() + "',");

        Map<String,List<ClientBehavior>> behaviors = getClientBehaviors();
        if (behaviors.containsKey(DEFAULT_EVENT) ) {
            String drop = behaviors.get(DEFAULT_EVENT).get(0).getScript(behaviorContext);
            writer.writeAttribute("drop:", drop, null);
        }

        writer.write("});");
        writer.write("});");
        writer.endElement("script");
    }

    // Private

    private boolean isRequestSource(FacesContext context) {
        return this.getClientId(context).equals(context.getExternalContext().getRequestParameterMap() .get("javax.faces.source"));
    }
}

这个用法就像......

<h:form id="frm">
      <div id="container" class="container">
        <ui:repeat var="row" value="#{homeBean.data}" id="dnd" >
          <h:panelGroup layout="block" id="draggable" styleClass="draggable">
            <h:outputText value="#{row}" />
          </h:panelGroup>
          <et:draggable  for="draggable" draggableSelector=".draggable" containTo="parent" revert="invalid" />
        </ui:repeat>

        <h:panelGroup layout="block" id="droppable" styleClass="droppable">
          <p>Drop Here!</p>
        </h:panelGroup>
      </div>

  <h:dataTable id="selectedItems" var="data" value="#{homeBean.selectedRows}">
    <h:column>
      <h:outputText value="#{data.name}" />
    </h:column>
  </h:dataTable>

      <et:droppable for="droppable" droppableSelector=".droppable" hoverClass="ui-state-hover" activeClass="ui-state-active" >
         <f:ajax listener="#{homeBean.objectDropped}" render="@form" event="drop" />
      </et:droppable>
    </h:form>

HomeBean.java

@ManagedBean
public class HomeBean {


    private List<String> data = new ArrayList<String>();
    private List<String> selectedRows = new ArrayList<String>();

    @PostConstruct
    public void init() {

        data.add("Value 1");
        data.add("Value 2");
    }

    public void objectDropped(DragDropEvent event) {
        selectedRows.add(event.getSourceId());
    }

    public List<String> getData() {
        return data;
    }

    public void setData(List<String> data) {
        this.data = data;
    }

    public List<String> getSelectedRows() {
        return selectedRows;
    }

    public void setSelectedRows(List<String> selectedRows) {
        this.selectedRows = selectedRows;
    }


}

2 个答案:

答案 0 :(得分:0)

在您的示例中,这是将数据从jquery事件通过JSF传递到服务器(其自解释的INMO)的一种方法

$( ".selector" ).bind( "drop", function(event, ui) { 
    $("#myInputHiddenID").val("someJsonStringCanBePlacedHereForExample");
    $("#myButtonID").click();
});


<h:commandButton id="myButtonID" action="#{myBean.myAction()}" style="display:none" >
    <f:ajax></f:ajax>
    <h:inputHidden id="myInputHiddenID" value="#{myBean.myStringData}" />
</h:commandButton>

public void myAction() {
     System.out.println(myStringData);
}

答案 1 :(得分:0)

当它结束时,我缺少的是在jQuery drop事件上添加一个Ajax Call,它引发了Droppable.java中定义的“drop”事件....

writer.write(" jsf.ajax.request(this,event,{execute: '");
writer.write(getClientId() +"', sourceId: ui.draggable.attr('id') , targetId: $(this).attr('id')}); ");

我仍然遇到生成事件的问题(它不会生成javax.faces.behavior.event的实例),但我想我应该为此打开一个新问题......