2010-11-27 7 views
3

Je pense que la meilleure façon de résoudre ce problème est juste pour coller mon code:JSF - Appel Ajax - Quel est le problème sur ce code?

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>   

Si je clique d'abord sur le bouton Modifier et que sur Confirmer Editer, je tente d'obtenir (comme résultat) la page avec l'étiquette ENFIN IM ICI ce Unfortunatly ne se produit pas. Je clique sur Modifier le bouton et après, si je clique sur Confirmer Modifier, rien ne se passe.

De quoi ai-je tort? Vive

MISE A JOUR AVEC LA NOUVELLE VERSION

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> 

Répondre

5

Eh bien, ce devient compliqué. L'appel de l'action UICommand dépend également du résultat de l'attribut rendered du composant ou de l'un de ses parents. Étant donné que le bean est dans la portée de la demande, la valeur profilePage revient par défaut à main dans la requête suivante. Par conséquent, l'attribut rendered de la section d'édition évalue false. Les boutons de la section d'édition n'appellent donc aucune action. Cela a été répondu dans votre previous question.

En théorie, marquer le bean @ViewScoped devrait corriger cela car il conserve l'état du bean dans les vues suivantes. Cependant, dans votre cas particulier, deux problèmes l'empêchent de fonctionner correctement. D'abord, vous utilisez un @ManagedProperty qui fait référence à une valeur qui est dans une portée plus courte (la portée #{param} est essentiellement portée par la demande). Vous devrez diviser le profilePage en un autre haricot et marquer ce @ViewScoped.

En second lieu, en raison d'un bug encore actuellement ouvert JSF2 (issue 1718), votre cas particulier ne fonctionne toujours pas parce que vous avez plusieurs <h:form> dans un état rendered différent qui sont tous attachés au même haricot. Cette situation spécifique conduirait à javax.faces.ViewState étant complètement manquant dans la réponse retournée. Cela entraînera la régénération du bean tronqué de la vue et sa recréation (et profilePage par défaut est de nouveau main). Comme une solution de contournement temporaire, vous devez extraire et fusionner les formulaires dans un formulaire en profile.xhtml, en tant qu'enfant direct de la première <h:panelGroup>.


Mise à jour: Si votre seule préoccupation est que vous voulez relier les haricots à l'autre, alors vous pouvez diviser les haricots comme suit:

@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; 

    // ... 
} 

Le Le bean tronqué est alors accessible dans le bean tronqué de la requête.

Ou, si vous vraiment voulez avoir un haricot unique, vous pouvez comme solution de contournement également remplacer @ManagedProperty comme suit:

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

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

    // ... 
} 
+0

Ohh. Au moins maintenant je comprends pourquoi il crée l'arbre des composants avec "main" au début de la procession. Je pense que j'ai besoin de changer de stratégie, parce que je veux le sélecteur bean avec RequestScope :) Malheureusement, je ne vois pas d'autres façons d'implémenter mon menu dinamique avec un appel ajax avec jsf ... – markzzz

+0

Vous voulez vraiment '@ ViewScoped'. Voir réponse mise à jour comment aborder cela. – BalusC

+0

Ouais, j'ai divisé en deux haricots différents (une meilleure visibilité). Essayé mais pour le moment il ne charge pas le rendu. Je vais essayer un peu plus! – markzzz