JSF - Ajax call - Что не так в этом коде? - PullRequest
3 голосов
/ 27 ноября 2010

Я думаю, что лучший способ решить эту проблему - просто вставить мой код:

Selector bean

@ManagedBean(name="selector")
@RequestScoped
public class Selector {
    @ManagedProperty(value="#{param.page}")
    private String page;
    private String profilePage;

    @PostConstruct
    public void init() {
        if(profilePage==null || profilePage.trim().isEmpty()) {
            this.profilePage="main";
        }

        if(page==null || page.trim().isEmpty()) {
            this.page="homepage";
        }
    }

    public String getProfilePage() { System.out.println("GET ="+profilePage); return profilePage; }
    public void setProfilePage(String profilePage) { this.profilePage=profilePage; }

    public String getPage() { return page; }
    public void setPage(String page) { this.page=page; }
}    

profile.xhtml

<h:panelGroup layout="block" id="profileContent">
    <h:panelGroup rendered="#{selector.profilePage=='main'}">
        <ui:include src="/profile/profile_main.xhtml" />
    </h:panelGroup>

    <h:panelGroup rendered="#{selector.profilePage=='edit'}">
        <ui:include src="/profile/profile_edit.xhtml" />
    </h:panelGroup>
</h:panelGroup>

profile_main.xhtml

<h:form id="formProfileMain" prependId="false">
    <h:panelGroup layout="block">
        <h:outputScript name="jsf.js" library="javax.faces" target="head" />

        <h:outputLabel value="MAIN" />

        <h:panelGroup layout="block" >
            <h:commandButton value="Edit Button">
                <f:setPropertyActionListener target="#{selector.profilePage}" value="edit" />
                <f:ajax event="action" render=":profileContent"/>
            </h:commandButton>
        </h:panelGroup>
    </h:panelGroup>
</h:form>    

profile_edit.xhtml

<h:panelGroup layout="block" id="profileEditContent">
    <h:panelGroup rendered="#{selector.profilePage=='edit'}">
        <h:form id="formProfileEdit" prependId="false">
            <h:panelGroup layout="block">
                <h:outputScript name="jsf.js" library="javax.faces" target="head" />

                <h:outputLabel value="EDIT" />

                <h:panelGroup layout="block">
                    <h:commandButton value="Confirm Edit">
                        <f:setPropertyActionListener target="#{selector.profilePage}" value="editConfirm" />
                        <f:ajax event="action" render=":profileEditContent"/>
                    </h:commandButton>

                    <h:commandButton value="Back">
                        <f:setPropertyActionListener target="#{selector.profilePage}" value="main" />
                        <f:ajax event="action" render=":profileEdit"/>
                    </h:commandButton>
                </h:panelGroup>
            </h:panelGroup>
        </h:form>
    </h:panelGroup>

    <h:panelGroup rendered="#{selector.profilePage=='editConfirm'}">
        <h:outputLabel value="FINALLY IM HERE" />
    </h:panelGroup>
</h:panelGroup>           

Если я сначала нажму Кнопка редактирования , а затем Подтвердить редактирование , я попытаюсьчтобы получить (как результат) страницу с меткой НАКОНЕЦ ИМ ЗДЕСЬ К сожалению, этого не происходит.Я нажимаю Редактировать кнопку и после, если я нажимаю Подтвердить Редактирование , ничего не происходит.

Что я не так?Приветствия

ОБНОВЛЕНИЕ С НОВОЙ ВЕРСИЕЙ

bean

@ManagedBean
@ViewScoped
public class ProfileSelector {
    private String profilePage;

    @PostConstruct
    public void init() {
        if(profilePage==null || profilePage.trim().isEmpty()) {
            this.profilePage="main";
        }
    }

    public String getProfilePage() { return profilePage; }
    public void setProfilePage(String profilePage) { this.profilePage=profilePage; }
}

profile.xhtml

<h:panelGroup layout="block" id="profileContent">
    <h:form id="formProfile" prependId="false">
        <h:outputScript name="jsf.js" library="javax.faces" target="head" />

        <h:panelGroup rendered="#{profileSelector.profilePage=='main'}">
            <ui:include src="/profile/profile_main.xhtml" />
        </h:panelGroup>

        <h:panelGroup rendered="#{profileSelector.profilePage=='edit'}">
            <ui:include src="/profile/profile_edit.xhtml" />
        </h:panelGroup>
    </h:form>
</h:panelGroup>

profile_main.xhtml

<h:panelGroup layout="block">            
    <h:outputLabel value="MAIN" />

    <h:panelGroup layout="block">
        <h:commandButton value="Edit Button">
            <f:setPropertyActionListener target="#{profileSelector.profilePage}" value="edit" />
            <f:ajax event="action" render=":profileContent"/>
        </h:commandButton>
    </h:panelGroup>
</h:panelGroup>

profile_edit.xhtml

<h:panelGroup layout="block" id="profileContentEdit">
    <h:panelGroup rendered="#{profileSelector.profilePage=='edit'}">
        <h:panelGroup layout="block">                
            <h:outputLabel value="EDIT" />

            <h:panelGroup layout="block" styleClass="profilo_3">
                <h:commandButton value="Confirm Edit">
                    <f:setPropertyActionListener target="#{profileSelector.profilePage}" value="editConfirm" />
                    <f:ajax event="action" render=":profileContentEdit"/>
                </h:commandButton>

                <h:commandButton value="Back">
                    <f:setPropertyActionListener target="#{profileSelector.profilePage}" value="main" />
                    <f:ajax event="action" render=":profileContent"/>
                </h:commandButton>
            </h:panelGroup>
        </h:panelGroup>
    </h:panelGroup>

    <h:panelGroup rendered="#{profileSelector.profilePage=='editConfirm'}">
        <h:outputLabel value="FINALLY Im HERE" />
    </h:panelGroup>
</h:panelGroup>

1 Ответ

5 голосов
/ 28 ноября 2010

Ну, это сложно. То, будет ли вызвано действие UICommand, также зависит от результата атрибута rendered компонента или одного из его родителей. Поскольку компонент находится в области запроса, profilePage по умолчанию возвращается к main в следующем запросе, поэтому атрибут rendered раздела редактирования оценивает false, поэтому кнопки в разделе редактирования не будут вызывать никаких действий. , Ответ на ваш предыдущий вопрос .

Теоретически, маркировка компонента @ViewScoped должна исправить это, потому что он сохраняет состояние компонента в последующих представлениях. Однако в вашем конкретном случае есть две проблемы, которые мешают ему работать должным образом.

Во-первых, вы используете @ManagedProperty, который относится к значению, которое находится в более короткой области (#{param} в основном находится в области запроса). Вам нужно будет разделить profilePage на другой компонент и пометить это @ViewScoped.

Во-вторых, из-за все еще открытой ошибки в JSF2 ( выпуск 1718 ) ваш конкретный случай все равно не будет работать, потому что у вас есть несколько <h:form> в другом состоянии rendered, которые все присоединены к тому же бобу. Эта конкретная ситуация может привести к тому, что javax.faces.ViewState будет полностью отсутствовать в возвращенном ответе. Это приведет к тому, что bean-объект области видимости будет выделен и воссоздан (и profilePage по умолчанию снова будет main). В качестве временного обходного пути, вам нужно извлечь и объединить формы в одну форму в profile.xhtml, как прямой потомок первого <h:panelGroup>.


Обновление : Если ваша единственная задача - соединить компоненты друг с другом, вы можете разделить компоненты следующим образом:

@ManagedBean
@RequestScoped
public class Selector {
    @ManagedProperty(value="#{param.page}")
    private String page;

    @ManagedProperty(value="#{profileSelector}")
    private ProfileSelector profileSelector;

    // ...
}

@ManagedBean
@ViewScoped
public class ProfileSelector {
    private String profilePage;

    // ...
}

Таким образом, bean-объект области видимости становится доступным в bean-объекте области видимости запроса.

Или, если вы действительно хотите иметь один компонент, вы можете в качестве обходного пути также заменить @ManagedProperty следующим образом:

@ManagedBean
@ViewScoped
public class Selector {
    private String page;
    private String profilePage;

    @PostConstruct
    public void init() {
        page = FacesContext.getCurrentInstance().getRequestParameterMap().get("page");
    }

    // ...
}
...