web-dev-qa-db-fra.com

JSF f: event preRenderView est déclenché par des appels f: ajax et des rendus partiels, quelque chose d'autre?

Nous avons donc un événement f:

   <f:metadata>
    <f:event type="preRenderView" listener="#{dashboardBacking.loadProjectListFromDB}"/>
   </f:metadata>

Qui est déclenché comme souhaité lors du chargement initial de la page (rendu).

Toutefois, cet événement preRenderView est également déclenché par un rendu de page partielle ajax, qui restitue un groupe h: panel avec l'id projectListing, comme ci-dessous.

<h:commandButton action="#{mrBean.addProject}" value="Create Project"
                                     title="Start a new project">
   <f:ajax render="projectListing" />
</h:commandButton>

Je veux seulement que dashboardBacking.loadProjectListFromDB soit appelé pour le rendu de la page initiale, mais pas lorsqu'il existe un rendu partiel ajax. Existe-t-il un événement ou une méthode plus approprié que je pourrais utiliser?

25
Andrew

Une autre option serait de placer votre fonctionnalité preRenderView dans une méthode @PostConstruct d'un bean géré ViewScoped. Cette logique serait exécutée lorsque le bean est initialisé et vous conservez la même instance du bean pour toutes vos demandes ajax jusqu'à ce que vous changiez de vue.

11
Brian Leathem

J'ai eu le même besoin il n'y a pas si longtemps. J'ai fini par utiliser quelque chose suggéré par BalusC

Il existe une méthode dans la classe FacesContext qui vous permet de savoir si vous avez affaire à une demande complète ou à un traitement partiel:

FacesContext.getCurrentInstance().isPostback()

De cette façon, vous pouvez toujours utiliser la technique preRenderView et vérifier s'il s'agit d'une publication dans l'écouteur. J'ai trouvé cela particulièrement utile car j'avais besoin d'un bean session car l'utilisateur devait naviguer vers une autre page et revenir. Si j'utilisais des haricots à la portée de vue (comme suggéré plus haut par Brian), je perdrais les informations dont j'avais besoin avant de partir.

31
Andre

Une autre possibilité consiste à vérifier si la requête est une requête ajax ou non dans la méthode preRenderView. Vous pouvez également effectuer le chargement de manière conditionnelle en tenant compte d'autres facteurs, tels que le fait que la demande soit ou non GET et que la validation échoue ou non (la validation des paramètres d'affichage peut échouer sur la page GET).

boolean getMethod = ((HttpServletRequest) fc.getExternalContext().getRequest()).getMethod().equals("GET") ? true : false;
boolean ajaxRequest = fc.getPartialViewContext().isAjaxRequest();
boolean validationFailed = fc.isValidationFailed();
7
Ryan
2
Kawu

Vous pouvez essayer de joindre l'écouteur d'événements preRenderView à un composant individuel plutôt qu'à la page. Choisissez un composant qui n'est pas rendu lors d'une requête Ajax.

1
Brian Leathem

Un petit problème est que les paramètres de vue n'ont pas été définis lorsque la méthode @PostConstruct est appelée. Je devais donc les obtenir explicitement:

FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("theParam");
0
Manuel Palacio

update : en fait, j'ai fini par faire la chose @PostConstruct, c'est beaucoup plus propre.

J'ai eu exactement le même problème aujourd'hui avec un haricot de sauvegarde de session-portée. À savoir, j'avais enregistré une méthode d'écoute d'événements sur le bean de sauvegarde de session enregistré avec le preRenderView. Mais j’ai trouvé qu’il s’était également déclenché lors de certaines opérations de tri Ajax sur un composant dataTable de PrimeFaces 3. J'ai donc finalement utilisé une variable d'instance booléenne sur le bean de sauvegarde à portée de session afin de m'assurer que le corps de la méthode du programme d'écoute d'événement était exécuté uniquement la première fois (le booléen agissait comme un indicateur). Je suis sûr que c'est plutôt naïf et probablement cassé dans certains cas, alors j'aimerais savoir pourquoi et comment cette approche simpliste pourrait échouer.

0