jsf 2 - template - Manejar los parámetros de vista en JSF después de la publicación
ui:composition primefaces (2)
Cuando busco, me da la impresión de que el parámetro de vista debe permanecer después de una publicación y leer userpage.jsf? UserId = 123, pero este no es el caso. ¿Cuál es realmente el comportamiento previsto?
Este comportamiento es correcto. La <h:form>
genera un elemento HTML <form>
con una URL de acción sin ningún parámetro de vista. La solicitud POST solo envía exactamente a esa URL. Si tiene la intención de mantener los parámetros de vista en la URL, básicamente hay 3 formas:
Trae algo de magia ajax.
<h:commandButton action="#{userPageController.doAction}" value="post"> <f:ajax execute="@form" render="@form" /> </h:commandButton>
De esta forma, la página solicitada inicialmente y, por lo tanto, también la URL de solicitud en la barra de direcciones del navegador permanece igual todo el tiempo.
Si corresponde (por ejemplo, para la navegación de página a página),
includeViewParams=true
en una solicitud GET y usaincludeViewParams=true
. Puede usar<h:link>
y<h:button>
para esto:<h:button outcome="nextview?includeViewParams=true" value="post" />
Sin embargo, esto tiene un exploit de seguridad EL en versiones de Mojarra anteriores a 2.1.6. Asegúrese de estar utilizando Mojarra 2.1.6 o posterior. Ver también el número 2247 .
Controle la generación de URL de acción de
<h:form>
usted mismo. Proporcione unViewHandler
personalizado (simplemente extiendaViewHandlerWrapper
) en donde usted hace el trabajo engetActionURL()
.public String getActionURL(FacesContext context, String viewId) { String originalActionURL = super.getActionURL(context, viewId); String newActionURL = includeViewParamsIfNecessary(context, originalActionURL); return newActionURL; }
Para que se ejecute, regístrelo en
faces-config.xml
siguiente manera:<application> <view-handler>com.example.YourCustomViewHandler</view-handler> </application>
Esto es también lo que está haciendo OmniFaces
<o:form>
. Admite un atributoincludeViewParams
adicional que incluye todos los parámetros de vista en la URL de acción del formulario:<o:form includeViewParams="true">
Actualización : la obtención de los parámetros de vista de la vista actual mediante programación (que es básicamente su segunda pregunta) debe hacerse de la siguiente manera:
Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(FacesContext.getCurrentInstance().getViewRoot());
for (UIViewParameter viewParam : viewParams) {
String name = viewParam.getName();
Object value = viewParam.getValue();
// ...
}
Tengo algunas páginas que necesitan un userId para funcionar, por lo tanto, el siguiente código:
userpage.xhtml
<!-- xmlns etc. omitted -->
<html>
<f:metadata>
<f:viewParam name="userId" value="#{userPageController.userId}"/>
</f:metadata>
<f:view contentType="text/html">
<h:head>
</h:head>
<h:body>
<h:form>
<h:commandButton action="#{userPageController.doAction}" value="post"/>
</h:form>
</h:body>
</f:view>
userPageController.java
@Named
@ViewScoped
public class userPageControllerimplements Serializable {
private static final long serialVersionUID = 1L;
@Inject protected SessionController sessionController;
@Inject private SecurityContext securityContext;
@Inject protected UserDAO userDAO;
protected User user;
protected Long userId;
public UserPage() {
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
if(!FacesContext.getCurrentInstance().isPostback()){
User u = userDAO.find(userId);
this.userId = userId;
this.user = u;
}
}
public void doAction(){
}
}
Sin embargo, después de llamar a doAction, el parámetro de vista en la url desaparece. El bean todavía funciona debido a su naturaleza viewcoped, pero arruina mis intentos de navegación futura. Cuando busco, me da la impresión de que el parámetro de vista debe permanecer después de una publicación y leer userpage.jsf? UserId = 123, pero este no es el caso. ¿Cuál es realmente el comportamiento previsto?
En relación con esto, he tratado de implementar la adición automática de parámetros de vista cuando navego a otra página donde deseo mantener el ID de usuario. Parece que funciona para otros, pero para mí, el ID de usuario en ViewRoot siempre es nulo. El siguiente código se usa para recuperar el parámetro de vista (sé que podría usar mi userId almacenado temporalmente en el bean para la navegación, pero esta solución sería mucho más elegante):
String name = "userId";
FacesContext ctx = FacesContext.getCurrentInstance();
ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler().getViewDeclarationLanguage(ctx, viewId);
ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId);
UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx);
UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME);
// Looking for a view parameter with the specified name
UIViewParameter viewParam = null;
for (UIComponent child : metadataFacet.getChildren()) {
if (child instanceof UIViewParameter) {
UIViewParameter tempViewParam = (UIViewParameter) child;
if (name.equals(tempViewParam.getName())) {
viewParam = tempViewParam;
break;
}
}
}
if (viewParam == null) {
throw new FacesException("Unknown parameter: ''" + name + "'' for view: " + viewId);
}
// Getting the value
String value = viewParam.getStringValue(ctx); // This seems to ALWAYS be null.
Una última idea es que los métodos setter todavía parecen funcionar, setUserId se llama con el valor correcto en la publicación.
¿He entendido por completo cómo funcionan los parámetros de vista, o hay algún tipo de error aquí? Creo que mi caso de uso debería ser extremadamente común y tener soporte básico en el marco.
¿Tengo razón en que para la solución 1 <f:ajax execute="@form" render="@form" />
para trabajar también habría que incluir algo así como
<f:param name="userId" value="#{userPageController.userId}"/>
dentro de la <h:commandButton>
?
Como se describe en https://.com/a/14026995/811046