Search code examples
javajsfprimefacesimagelist

How to use p:graphicImage with StreamedContent inside ui:repeat/h:dataTable/p:dataTable?


I have a list of objects with a StreamedContent property and I need to show it in the <p:graphicImage> component.

<ui:repeat value="#{testuser.answers}" var="imageanswers">
    <p:graphicImage value="#{imageanswers.imageAnswer}" alt="Image" width="200" height="100" />
    <br />
</ui:repeat>

But this isn't shown. It displays the alt text instead. I saw this other post Use of p:graphicImage in ui:repeat or p:dataTable, but I don't understand the getImages() method.


Solution

  • I don´t get the getImages method

    The getImages method is the getter for the images property which happens to be set as the value attribute of the <ui:repeat>.

    So why is it a list of String objects? I thought that the graphicImage component must have a value that is a StreamedContent?

    Yes its value must be a StreamedContent, but you can't loop through StreamedContents to build a list of images on the page. The reason why is that the graphicImage Primefaces component renders on the HTML page to a standard HTML <img> tag. If you were to look at the console output for Firebug or Fiddler or some other tool, you will notice the request for the JSF page, and then you will also notice a seperate request for each image resource the page references to. These image resources have to be loaded one by one from a series of seperate requests, so how is the ManagedBean supposed to know which request maps to which image?

    This is why the repeat component must iterate over a list of unique image ids because in essence when it builds a graphicImage component it is building an HTML image tag with a reference to the webserver for a specific image, identified by id. To send this unique id, they are using the <f:param> facelets tag which adds the unique identified as an HTTP request parameter.

    <ui:repeat value="#{bean.images}" var="imageID">
       <p:graphicImage value="#{bean.image}">
          <f:param name="imageID" value="#{imageID}" />
       </p:graphicImage>
    </ui:repeat>
    

    The value attribute of the repeated graphicImage is a managed bean property getter and it is the same method for loading the image that every other graphicImage component gets. The difference is that in the image property getter method we can uses the FacesContext to get our unique imageID that was passed as an HTTP request parameter.

    public StreamedContent getImage() {
         FacesContext context = FacesContext.getCurrentInstance();
         HttpServletRequest myRequest = (HttpServletRequest) context.getExternalContext().getRequest();
         String imageID = (String) myRequest.getParameter("imageID");
         return new DefaultStreamedContent(new ByteArrayInputStream(themeFacade.find(Long.parseLong(imageID)).getImage()));
    }