为什么在单击CommandButton组件时会触发两个AJAX请求?

时间:2016-01-25 10:37:15

标签: ajax jsf primefaces

我想在不使用xhtml的情况下在纯java中编写自定义jsf组件。

我使用Mojarra 2.2和Primefaces 5.1。

到目前为止。

import java.io.IOException;
import java.util.Date;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UINamingContainer;
import javax.faces.component.html.HtmlPanelGroup;
import javax.faces.context.FacesContext;
import javax.faces.event.FacesEvent;
import org.primefaces.behavior.ajax.AjaxBehavior;
import org.primefaces.component.autocomplete.AutoComplete;
import org.primefaces.component.commandbutton.CommandButton;
import org.primefaces.component.inputtext.InputText;

@FacesComponent(createTag = true, tagName = "picker", namespace = "http://jsdfdemo")
public class Picker extends UINamingContainer {

    private String text;

    public Picker() {

    }

    @Override
    public void processRestoreState(FacesContext context, Object state) {
        super.processRestoreState(context, state); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        if (!context.isPostback()) {
            HtmlPanelGroup rootPanel = new HtmlPanelGroup();
            rootPanel.setLayout("block");
            rootPanel.setId("root_panel");

            InputText autoComplete = new InputText();
            autoComplete.setId("autocomplete");
            autoComplete.setValue(this.text);
            CommandButton clearButton = new CommandButton();
            clearButton.setId("clear");
            clearButton.setValue("Clear");
            CommandButton pickButton = new CommandButton();
            pickButton.setAjax(true);
            pickButton.setUpdate("@form");
            pickButton.setId("pick");
            pickButton.setValue("Pick");

            AjaxBehavior pickClickBehavior = new AjaxBehavior();
            pickClickBehavior.setUpdate(autoComplete.getId());
            pickClickBehavior.setProcess("@this");
            pickButton.addClientBehavior(pickButton.getDefaultEventName(), pickClickBehavior);

            rootPanel.getChildren().add(autoComplete);
            rootPanel.getChildren().add(clearButton);
            rootPanel.getChildren().add(pickButton);

            this.getChildren().add(rootPanel);
        }
        super.encodeBegin(context); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void decode(FacesContext context) {
        super.decode(context); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void queueEvent(FacesEvent event) {
        super.queueEvent(event);
        if (event.getComponent().equals(this.getPickButton())) {
            this.getAutoComplete().setValue(new Date());
        }
    }

    @Override
    public String getFamily() {
        return UINamingContainer.COMPONENT_FAMILY;
    }

    public HtmlPanelGroup getRootPanel() {
        return (HtmlPanelGroup) this.findComponent("root");
    }

    public InputText getAutoComplete() {
        return (InputText) this.findComponent("autocomplete");
    }

    public CommandButton getClearButton() {
        return (CommandButton) this.findComponent("clear");
    }

    public CommandButton getPickButton() {
        return (CommandButton) this.findComponent("pick");
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

我希望选择按钮更改autoComplete的值(实际上是一个InputText)。我在自定义组件的queueEvent方法中执行此操作。我不知道这是否适合这样做。

我也不确定encodeBegin是构建组件树的正确位置。 if(!context.isPostback())确保组件仅在初始GET上创建一次,但不能用于回发请求。

这是呈现给客户的内容。

<div id="j_idt43:j_idt44:root_panel">
    <input id="j_idt43:j_idt44:autocomplete" 
            name="j_idt43:j_idt44:autocomplete" 
            type="text" 
            class="ui-inputfield ui-inputtext ui-widget ui-state-default ui-corner-all" 
            role="textbox" 
            aria-disabled="false"
            aria-readonly="false">
    <button id="j_idt43:j_idt44:clear" 
            name="j_idt43:j_idt44:clear" 
            class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" 
            onclick="PrimeFaces.ab({s:'j_idt43:j_idt44:clear'});return false;" 
            type="submit" 
            role="button" 
            aria-disabled="false">
        <span class="ui-button-text ui-c">Clear</span>
    </button>
    <button id="j_idt43:j_idt44:pick" 
            name="j_idt43:j_idt44:pick" 
            class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" 
            onclick="PrimeFaces.bcn(this,event,[function(event){PrimeFaces.ab({s:'j_idt43:j_idt44:pick',e:'click',p:'j_idt43:j_idt44:pick',u:'j_idt43:j_idt44:autocomplete'});},function(event){PrimeFaces.ab({s:'j_idt43:j_idt44:pick',u:'j_idt43'});return false;}]);" 
            type="submit" 
            role="button" 
            aria-disabled="false">
            <span class="ui-button-text ui-c">Pick</span>
    </button>
</div>

这里的问题是,单击选择按钮时会触发两个AJAX请求,尽管只注册了一个AjaxBehavior。第一个表现得像预期的那样。视图已更新,我可以在输入文本组件中看到当前日期。但随后会触发第二个AJAX请求(在第一个完成之后)并清除输入文本。

第一个请求的参数是。

javax.faces.partial.ajax:true
javax.faces.source:j_idt43:j_idt44:pick
javax.faces.partial.execute:j_idt43:j_idt44:pick
javax.faces.partial.render:j_idt43:j_idt44:autocomplete
javax.faces.behavior.event:click
javax.faces.partial.event:click
j_idt43:j_idt43
j_idt43:j_idt44:autocomplete:
javax.faces.ViewState:3283049963151483162:-8986718217282610712

第二个是。

javax.faces.partial.ajax:true
javax.faces.source:j_idt43:j_idt44:pick
javax.faces.partial.execute:@all
javax.faces.partial.render:j_idt43
j_idt43:j_idt44:pick:j_idt43:j_idt44:pick
j_idt43:j_idt43
j_idt43:j_idt44:autocomplete:Mon Jan 25 11:17:05 CET 2016
javax.faces.ViewState:3283049963151483162:-8986718217282610712

有什么建议吗?

0 个答案:

没有答案