Cómo mostrar los detalles de la fila actual de p:dataTable en ap:dialog y actualizar después de guardar

Resuelto AlexSC asked hace 9 años • 1 respuestas

Tengo una aplicación JSF 2 que tiene dos páginas, una para enumerar los estudiantes y otra para mostrar los detalles de un estudiante determinado. La página de listado tiene un enlace a la página de detalles en cada fila de la tabla de estudiantes, que abre una nueva pestaña en el navegador para mostrar esos detalles cuando se hace clic.

Ahora los requisitos cambiaron para no mostrar más detalles en una nueva pestaña, sino en un cuadro de diálogo modal en la página de listado.

Mi idea es simplemente incrustar el contenido de la página de detalles en el cuadro de diálogo modal para que la página de listado no sea demasiado grande ni difícil de mantener. Aquí empiezan mis dudas. Después de investigar un poco, cambié el enlace en cada fila del listado al siguiente botón:

<p:commandButton value="Details" type="button"
                 onclick="PF('dialog-details').show()">
</p:commandButton>

El diálogo se declara de la siguiente manera:

<p:dialog widgetVar="dialog-details" header="Details" modal="true" width="95%">
    <ui:include src="student_details.xhtml">
        <ui:param name="id" value="#{student.id}"/>
    </ui:include>
</p:dialog>

Finalmente, la página de detalles se cambió para quedar algo como esto:

<ui:composition
    xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui" xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">

    <f:metadata>
        <f:viewParam name="id" value="#{studentBean.id}" />
    </f:metadata>

    <h1 class="title ui-widget-header ui-corner-all">Details of #{studentBean.bean.name} / #{studentBean.bean.number}</h1>
</ui:composition>                       

Cuando hago clic en el botón, el cuadro de diálogo realmente se muestra y el contenido es la página de detalles. Veo el siguiente contenido en el cuadro de diálogo:

Details of  / 

No hay ningún error, pero los datos que deberían mostrarse no lo son. Se estableció un punto de interrupción StudentBean.setId()(este método carga una propiedad nombrada beancon la Studentinstancia correspondiente a la identificación pasada) pero nunca se alcanza.

Después de pensarlo un tiempo, llegué a comprender por qué no funciona. El parámetro pasado a la página de detalles es student.id, pero studentes el nombre utilizado en el varque <p:datatable/>muestran todos los estudiantes, por lo que studentno es válido en <p:dialog/>el que está fuera del <p:datatable/>.

Entonces, lo que necesito es una forma de mostrar el diálogo usando la identificación del estudiante correspondiente en una fila determinada. Idealmente, me gustaría una llamada ajax aquí, para que los detalles se carguen solo cuando sea necesario.

¿Algunas ideas?

AlexSC avatar Jan 30 '15 19:01 AlexSC
Aceptado

El botón debe ser un botón ajax que establece la entidad iterada actualmente en el bean, luego actualiza el contenido del cuadro de diálogo y finalmente lo muestra. El cuadro de diálogo solo debe hacer referencia a esa entidad en el bean y actualizar la lista y la tabla al guardar. Es muy importante que el diálogo se coloque fuera del formulario principal y que tenga su propio formulario.

Aquí hay un ejemplo de inicio:

<h:form id="master">
    <p:dataTable value="#{bean.entities}" var="entity">
        <p:column>#{entity.property1}</p:column>
        <p:column>#{entity.property2}</p:column>
        <p:column>#{entity.property3}</p:column>
        ...
        <p:column>
            <p:commandButton value="View" action="#{bean.setEntity(entity)}" 
                update=":detail" oncomplete="PF('detail').show()" />
        </p:column>
    </p:dataTable>
</h:form>

<p:dialog id="detail" widgetVar="detail">
    <h:form>
        <p:inputText value="#{bean.entity.property1}" />
        <p:inputText value="#{bean.entity.property2}" />
        <p:inputText value="#{bean.entity.property3}" />
        ...
        <p:button value="Close" onclick="PF('detail').hide(); return false" />
        <p:commandButton value="Save" action="#{bean.save}" 
            update=":master" oncomplete="if(!args.validationFailed) PF('detail').hide()" />
    </h:form>
</p:dialog>

Con esto dentro de un @ViewScopedfrijol:

private List<Entity> entities; // +getter
private Entity entity; // +getter+setter

@EJB
private EntityService entityService;

@PostConstruct
public void load() {
    entities = entityService.list();
    entity = null;
}

public void save() {
    entityService.save(entity);
    load();
}

Ver también:

  • Crear páginas maestras y de detalles para entidades, cómo vincularlas y qué alcance de bean elegir
  • Creación de una tabla y un cuadro de diálogo maestro-detalle, cómo reutilizar el mismo cuadro de diálogo para crear y editar
  • Mantenga p:diálogo abierto cuando se produzca un error de validación después del envío
  • Diferencia entre atributos renderizados y visibles de <p:dialog>
  • Cómo mostrar el cuadro de diálogo solo al completarse el envío exitoso del formulario
BalusC avatar Jan 30 '2015 14:01 BalusC