Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
RE: Extend Primefaces FileUpload Component to upload files from Document Li
			Hi, 
I would like to extend the functionality of the Primefaces component FileUpload so instead of uploading a file from my local system, do that from Liferay's Document Library.
        
To do that, I have followed the method described here:
https://community.liferay.com/en_GB/blogs/-/blogs/open-document-library-popup-in-custom-portlet
http://www.liferaysavvy.com/2013/11/working-with-liferay-alloy-ui-dialogs.html
After modifying some things to adapt it to Lifery 6.2 (which is the environment where I am working) it works in a portlet, but what I need is this to work as a Primefaces Component, so I have extended FileUpload and FileUploadRenderer as described in here:
https://www.logicbig.com/tutorials/java-ee-tutorial/jsf/custom-component-and-renderer.html
Now I need to overwrite the function encodeChooseButton (source of fileUploadRenderer in here: https://github.com/primefaces/primefaces/blob/master/src/main/java/org/primefaces/component/fileupload/FileUploadRenderer.java) to change the behavior of the button. This is my final code:
I am going to paste now the the code for the portlet where this code work propertly to compare it (view.jsp):
The problem comes when the DialogIframe is loaded, this is the result (see TestUpload html.jpg. In the left we can see the portlet, in the right the primefaces TestComponent).
If we take a look at the generated html, we can see that the portlet version has generated an iframe element inside the modal-body and the prime faces version doesn't.
And if we take a look at the generated javascript (see TestUploadDoclib javascript.jpg), we can see that they are the same. I have to hide the url because of data protection, but I have tested it just copying it into the browser and it works, it lead me to the document library.
I can't figure out why this is happening, I don't get any error message. It seems like the Plugin.DialogIframe is not being loaded into the responseWriter, but the rest of the javascript, even the alloy-ui code yes.
Can anyone give me a hand with this?
		I would like to extend the functionality of the Primefaces component FileUpload so instead of uploading a file from my local system, do that from Liferay's Document Library.
To do that, I have followed the method described here:
https://community.liferay.com/en_GB/blogs/-/blogs/open-document-library-popup-in-custom-portlet
http://www.liferaysavvy.com/2013/11/working-with-liferay-alloy-ui-dialogs.html
After modifying some things to adapt it to Lifery 6.2 (which is the environment where I am working) it works in a portlet, but what I need is this to work as a Primefaces Component, so I have extended FileUpload and FileUploadRenderer as described in here:
https://www.logicbig.com/tutorials/java-ee-tutorial/jsf/custom-component-and-renderer.html
Now I need to overwrite the function encodeChooseButton (source of fileUploadRenderer in here: https://github.com/primefaces/primefaces/blob/master/src/main/java/org/primefaces/component/fileupload/FileUploadRenderer.java) to change the behavior of the button. This is my final code:
@FacesRenderer(componentFamily = "Test", rendererType = "TestComponent")
public class TestRenderer extends FileUploadRenderer {
    @Override
    protected void encodeChooseButton(FacesContext context, FileUpload fileUpload, boolean disabled) throws IOException {
        
        PortletRequest request = (PortletRequest) context.getExternalContext().getRequest();
        ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
        long dlScopeGroupId = themeDisplay.getScopeGroupId();
        LiferayPortletURL documentLibURL = PortletURLFactoryUtil.create(request, PortletKeys.DYNAMIC_DATA_MAPPING, themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
        try {
            documentLibURL.setWindowState(LiferayWindowState.POP_UP);
            documentLibURL.setPortletMode(PortletMode.VIEW);
        } catch (WindowStateException | PortletModeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        documentLibURL.setParameter("struts_action","/dynamic_data_mapping/select_document_library");
        documentLibURL.setParameter("groupId", String.valueOf(dlScopeGroupId));
        
        log.info("This is the url: " + documentLibURL);        
        
        ResponseWriter writer = context.getResponseWriter();
        String clientId = fileUpload.getClientId(context);
        String label = fileUpload.getLabel();
        String cssClass = HTML.BUTTON_TEXT_ICON_LEFT_BUTTON_CLASS + " " + FileUpload.CHOOSE_BUTTON_CLASS;
        cssClass = isValueBlank(label) ? FileUpload.BUTTON_ICON_ONLY + " " + cssClass : cssClass;
        String tabindex = (disabled) ? "-1" : "0";
        if (disabled) {
            cssClass += " ui-state-disabled";
        }
        writer.startElement("span", null);
        writer.writeAttribute("class", cssClass, null);
        writer.writeAttribute("tabindex", tabindex, null);
        writer.writeAttribute("role", "button", null);
        writer.writeAttribute("aria-labelledby", clientId + "_label", null);
        writer.writeAttribute("onclick", "showDocLib()", null);
        //button icon
        writer.startElement("span", null);
        writer.writeAttribute("class", HTML.BUTTON_LEFT_ICON_CLASS + " ui-icon-plusthick", null);
        writer.endElement("span");
        //text
        writer.startElement("span", null);
        writer.writeAttribute("id", clientId + "_label", null);
        writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);
        if(isValueBlank(label)) {
            writer.write(" ");
        }
        else {
            writer.writeText(label, "value");
        }
        
        writer.endElement("span");
            writer.startElement("div", null);
            writer.writeAttribute("id",  "modal" , null);
            writer.endElement("div");
//        if (!disabled) {
//            encodeInputField(context, fileUpload, clientId);
//        }
        writer.endElement("span");
        writer.startElement("script", null);
        writer.write("function showDocLib(){");
            writer.write("var url = '" + documentLibURL + "';");
            writer.write("AUI().ready('aui-modal','aui-dialog-iframe','aui-overlay-manager','liferay-portlet-url', function(A) {");
                writer.write("window.myDialog = new A.Modal(");
                    writer.write("{");
                    writer.write("centered: true,");
                    writer.write("render: '#modal'");
                    writer.write("}");
                writer.write(").plug(A.Plugin.DialogIframe,{");
                    writer.write("uri: url," );
                    writer.write("iframeCssClass: 'dialog-iframe'");
                writer.write("}");
                writer.write(").render();");
            writer.write("});");
        writer.write("}");
        writer.endElement("script");
    }
}
I am going to paste now the the code for the portlet where this code work propertly to compare it (view.jsp):
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@ taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %>
<%@page import="com.liferay.portal.theme.ThemeDisplay"%>
<%@page import="com.liferay.portal.kernel.portlet.LiferayPortletURL"%>
<%@page import="com.liferay.portal.kernel.util.WebKeys"%>
<%@page import="com.liferay.portlet.PortletURLFactoryUtil"%>
<%@page import="com.liferay.portal.util.PortletKeys"%>
<%@page import="javax.portlet.PortletRequest"%>
<%@page import="com.liferay.portal.kernel.portlet.LiferayWindowState"%>
<%@page import="javax.portlet.PortletMode"%>
<portlet:defineobjects />
<% 
ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
long dlScopeGroupId = themeDisplay.getScopeGroupId();
LiferayPortletURL documentLibURL = PortletURLFactoryUtil.create(request, PortletKeys.DYNAMIC_DATA_MAPPING, themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
documentLibURL.setWindowState(LiferayWindowState.POP_UP);
documentLibURL.setPortletMode(PortletMode.VIEW);
documentLibURL.setParameter("struts_action","/dynamic_data_mapping/select_document_library");
documentLibURL.setParameter("groupId", String.valueOf(dlScopeGroupId));
%> 
<input type="hidden" name="<portlet:namespace/>documentLibraryInput" id="<portlet:namespace/>documentLibraryInput">
<div class="profile-image">
    <img class="journal-image" hspace="0" id="<portlet:namespace/>article-image" src="" style="width:82px;height:83px" vspace="0">
</div>
<div class="image-data">
    <label>
        <input name="articleId" id="articleId" type="button" value="Select From DocLib" onclick="showDocLib()">
    </label>
</div> 
<div id="modal"></div>
<script>
function showDocLib(){
    var url = '<%= documentLibURL %>';
    //Dialog is an AlloyUI 1.5 component. Since Liferay 6.2 uses AlloyUI 2.0, Dialog will not work in Liferay 6.2. Instead we need to use the AlloyUI 2.0 Modal component
    AUI().use('aui-modal','aui-dialog-iframe','aui-overlay-manager','liferay-portlet-url', function(A) {
        var modal = new A.Modal(
          {
            centered: true,
            render: '#modal'
          }
        ).plug(A.Plugin.DialogIframe,{
            uri: url,
            iframeCssClass: 'dialog-iframe'
        }
        ).render();
    });
}
</script>
<script charset="utf-8" type="text/javascript">
    function _166_selectDocumentLibrary(url) {
        document.getElementById("<portlet:namespace/>documentLibraryInput").value = url;
        var pic1 = document.getElementById("<portlet:namespace/>article-image");
        pic1.src = url;
        var iframe = document.getElementById('documentDetails');
        iframe.parentNode.removeChild(iframe);
    }
</script>The problem comes when the DialogIframe is loaded, this is the result (see TestUpload html.jpg. In the left we can see the portlet, in the right the primefaces TestComponent).
If we take a look at the generated html, we can see that the portlet version has generated an iframe element inside the modal-body and the prime faces version doesn't.
And if we take a look at the generated javascript (see TestUploadDoclib javascript.jpg), we can see that they are the same. I have to hide the url because of data protection, but I have tested it just copying it into the browser and it works, it lead me to the document library.
I can't figure out why this is happening, I don't get any error message. It seems like the Plugin.DialogIframe is not being loaded into the responseWriter, but the rest of the javascript, even the alloy-ui code yes.
Can anyone give me a hand with this?
				
				
					Kyle Joseph Stiemann, modified 6 Years ago.
				
				
				
				
					
					
						
							Liferay Master
						
					
					
						
							
							
								Posts: 760
							
						
					
					
						
							Join Date: 1/14/13
						
					
					
						
							
							
							
						
						
							
	
		
			
				
					
						
	
		
	
	
	
		
			Recent Posts
		
	
					
				
				
		
	
						
					
				
				
				
					
						
						
							
	
		
			
		
		
	
	
						
					
				
			
			
			Hi Javier,
Can you also include a simple JSF view (.xhtml) that uses your component and reproduces this issue?
Seems like the default PrimeFaces renderer is still being used instead of your custom renderer.
I think you need to change the following line:
- Kyle
		Can you also include a simple JSF view (.xhtml) that uses your component and reproduces this issue?
Seems like the default PrimeFaces renderer is still being used instead of your custom renderer.
I think you need to change the following line:
@FacesRenderer(componentFamily = "Test", rendererType = "TestComponent")
To this:@FacesRenderer(componentFamily = "org.primefaces.component.FileUpload",
    rendererType = "org.primefaces.component.FileUploadRenderer")
In order to properly override p:fileUpload's renderer.- Kyle
			Hi Kyle,
Thank you for your quick answer,
I might have missed an explanation,
I already have another button which uses <p:fileUpload>, so what I have tried is to create a new Component that extends FileUpload functionality. That's why I am using componentFamily = "Test" and rendererType = "TestComponent".
I have been following the instructions in https://www.logicbig.com/tutorials/java-ee-tutorial/jsf/custom-component-and-renderer.html.
Those are all the classes that I am using:
And this is the JSF view. As you can see in the line 58 the original p:fileUpload is being used for another button, so I need a different component to achieve this new functionality. You can see it in the line 65.
The newsletterElementBean.type is rendered when clicking in the buttons showed in TestUploadDoclib html.JPG in my previous post (Bild mit Überschrift, TestElement, TestTextArea, TestUploadDocLib...).
Besides of that, I think the TestRenderer it is actually working, I tested it with a different component before than fileUpload and it worked. And even now it you take a look at the generated html and javascript aro not the original ones, but the overwritten in TestRenderer.
As an examplo of that, I attach a screenshot of the execution when I add a bodyContent to the js function:
And of course if I do the same in the other portlet, it still works, the bodyContent is overwrite by the .plug function, that's why I think the problem is related with loading the DialogIframe inside the responseWriter.
Please, let me know what you think and if you need anything else.
Thanks a lot.
Javier.
		Thank you for your quick answer,
I might have missed an explanation,
I already have another button which uses <p:fileUpload>, so what I have tried is to create a new Component that extends FileUpload functionality. That's why I am using componentFamily = "Test" and rendererType = "TestComponent".
I have been following the instructions in https://www.logicbig.com/tutorials/java-ee-tutorial/jsf/custom-component-and-renderer.html.
Those are all the classes that I am using:
@FacesComponent(value = "TestComponent", createTag = true, tagName = "testComponent", namespace = "http://example.com/tags")
public class TestComponent extends FileUpload {
    public TestComponent() {
        setRendererType("TestComponent");
    }
    
    @Override
    public String getFamily() {
         return "Test";
    }
}@ManagedBean
@RequestScoped
public class TestBean {
    public String getMessage() {
        return "Hi there!";
    }
    public LocalDateTime getTime() {
        return LocalDateTime.now();
    }
}And this is the JSF view. As you can see in the line 58 the original p:fileUpload is being used for another button, so I need a different component to achieve this new functionality. You can see it in the line 65.
The newsletterElementBean.type is rendered when clicking in the buttons showed in TestUploadDoclib html.JPG in my previous post (Bild mit Überschrift, TestElement, TestTextArea, TestUploadDocLib...).
<!--?xml version="1.0"?-->
<f:view     xmlns="http://www.w3.org/1999/xhtml"  xmlns:c="http://java.sun.com/jsp/jstl/core"  xmlns:bridge="http://liferay.com/faces/bridge"  xmlns:f="http://java.sun.com/jsf/core"  xmlns:h="http://java.sun.com/jsf/html"  xmlns:ui="http://java.sun.com/jsf/facelets"  xmlns:p="http://primefaces.org/ui"  xmlns:aui="http://liferay.com/tld/aui"  xmlns:portlet="http://java.sun.com/portlet_2_0"  xmlns:t="http://xmlns.jcp.org/jsf/component"  xmlns:v="http://example.com/tags">
<!-- Dialog to add Content -->
<h:form id="elementDialogForm">
    <p:growl id="dialogGrowl" showDetail="true" />
    <p:dialog header="Neues Newsletterelement hinzufügen"         id="addElementToContentId" widgetvar="addElementToContent">
        <p:panelgrid styleclass="noBorder" id="elementGrid">
            <p:row rendered="#{paramSession.nElement.id != null}">
                <p:column>
                    <h:outputtext value="#{paramSession.nElement.record.getFieldValue('Bezng')} ändern" style="font-weight:bold;" />
                </p:column>
            </p:row>
            <p:row rendered="#{paramSession.nElement.id == null}">
                <p:column>
                    <h:outputtext value="#{paramSession.nElement.record.getFieldValue('Bezng')} hinzufügen" style="font-weight:bold;" />
                </p:column>
            </p:row>
            <p:row rendered="#{newsletterElementBean.type('textarea')}">
                <p:column>
                    <p:editor value="#{paramSession.nElement.text}"           style="width:500px;height:275px;"  controls="bold italic underline strikethrough subscript superscript | size | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source" />
                </p:column>
            </p:row>
            <p:row rendered="#{newsletterElementBean.type('textinput')}">
                <p:column><p:inputtext value="#{paramSession.nElement.text}" placeholder="Inhalt" /></p:column>
            </p:row>
            <p:row rendered="#{newsletterElementBean.type('link')}">
                <p:column><p:inputtext value="#{paramSession.nElement.text}" placeholder="Inhalt" /></p:column>
            </p:row>
            <p:row  rendered="#{newsletterElementBean.type('link')}">
                <p:column><p:inputtext value="#{paramSession.nElement.link}" placeholder="Link" /></p:column>
            </p:row>
            <p:row rendered="#{newsletterElementBean.type('wysiwyg')}">
                <p:column>
                    <p:editor value="#{paramSession.nElement.text}"           style="width:500px;height:275px;"  controls="bold italic underline strikethrough subscript superscript | size | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source" />
                </p:column>
            </p:row>
            <p:row rendered="#{newsletterElementBean.type('upload')}">
                <p:column>
                    <p:fileupload fileUploadListener="#{fileUploadView.handleFileUpload}" mode="advanced"          update="messages" auto="false" allowTypes="/(\.|\/)(gif|jpe?g|png|jpg)$/" />
                    <p:growl id="messages" showDetail="true" />
                </p:column>
            </p:row>
            <p:row rendered="#{newsletterElementBean.type('uploadDocLib')}">
                <p:column>
                    <v:testcomponent />
                </p:column>
            </p:row>
            <p:row rendered="#{newsletterElementBean.type('noinput')}">
                <p:column>
                    <h:outputtext value="Es wird keine Eingabe für dieses Element benötigt" />
                </p:column>
            </p:row>
        </p:panelgrid>
        
        <f:facet name="footer">
            <div style="overflow:auto;">
                <p:commandbutton icon="fa fa-close" value="Abbrechen"          style="float:left;" action="#{newsletterElementBean.clearNElement()}" oncomplete="PF('addElementToContent').hide();" />
                                                                  
                <p:commandbutton icon="fa fa-plus-circle"          value="Ändern" style="float:right;" rendered="#{newsletterElementBean.editable}" action="#{newsletterElementBean.updateToContent()}" process=":elementDialogForm, :elementForm:nlLayout" update=":elementForm:nlLayout, :elementDialogForm:dialogGrowl, :mouseoverScript" oncomplete="PF('addElementToContent').hide();" />
                                 
                <p:commandbutton icon="fa fa-plus-circle"          value="Übernehmen" style="float:right;" rendered="#{!newsletterElementBean.editable}" action="#{newsletterElementBean.addToContent()}" process=":elementDialogForm" update=":elementForm:nlLayout, :elementDialogForm:dialogGrowl, :mouseoverScript" oncomplete="PF('addElementToContent').hide();">
                                 
                    <f:setpropertyactionlistener value="#{paramSession.nElement}" target="#{paramSession.nElement}" />
                </p:commandbutton>
            </div>
        </f:facet>
    </p:dialog>
</h:form>
<h:form>
    <p:dialog header="Bild auswählen"></p:dialog>
</h:form>
</f:view>Besides of that, I think the TestRenderer it is actually working, I tested it with a different component before than fileUpload and it worked. And even now it you take a look at the generated html and javascript aro not the original ones, but the overwritten in TestRenderer.
As an examplo of that, I attach a screenshot of the execution when I add a bodyContent to the js function:
And of course if I do the same in the other portlet, it still works, the bodyContent is overwrite by the .plug function, that's why I think the problem is related with loading the DialogIframe inside the responseWriter.
writer.startElement("script", null);
        writer.write("function showDocLib(){");
            writer.write("var url = '" + documentLibURL + "';");
            writer.write("AUI().use('aui-modal','aui-dialog-iframe','aui-overlay-manager','liferay-portlet-url', function(A) {");
                writer.write("var modal = new A.Modal(");
                    writer.write("{");
                    writer.write("bodyContent: 'This is a test',");
                    writer.write("centered: true,");
                    writer.write("render: '#modal'");
                    writer.write("}");
                writer.write(").plug(A.Plugin.DialogIframe,{");
                    writer.write("uri: url," );
                    writer.write("iframeCssClass: 'dialog-iframe'");
                writer.write("}");
                writer.write(").render();");
            writer.write("});");
        writer.write("}");
        writer.endElement("script");Please, let me know what you think and if you need anything else.
Thanks a lot.
Javier.
Attachments:
				
				
					Kyle Joseph Stiemann, modified 6 Years ago.
				
				
				
				
					
					
						
							Liferay Master
						
					
					
						
							
							
								Posts: 760
							
						
					
					
						
							Join Date: 1/14/13
						
					
					
						
							
							
							
						
						
							
	
		
			
				
					
						
	
		
	
	
	
		
			Recent Posts
		
	
					
				
				
		
	
						
					
				
				
				
					
						
						
							
	
		
			
		
		
	
	
						
					
				
			
			
			Could you attach the simplest JSF portlet that can reproduce this issue so I can take a look at it locally? You should be able to provide a view with only your custom PrimeFaces component and include the custom component and I think that should be enough.
- Kyle
		- Kyle
			I can't replicate the whole functionality of the components in a simple way because it needs to reference a lot of clases and functions, but I have just created a simple porlet with the two main components, the simple p:fileUpload and the extended that is trying to access the document library.
I attach it so you can test it in your local.
I hope you find it useful.
Thank you very much for your time.
Javier.
		I attach it so you can test it in your local.
I hope you find it useful.
Thank you very much for your time.
Javier.
Attachments:
				
				
					Kyle Joseph Stiemann, modified 6 Years ago.
				
				
				
				
					
					
						
							Liferay Master
						
					
					
						
							
							
								Posts: 760
							
						
					
					
						
							Join Date: 1/14/13
						
					
					
						
							
							
							
						
						
							
	
		
			
				
					
						
	
		
	
	
	
		
			Recent Posts
		
	
					
				
				
		
	
						
					
				
				
				
					
						
						
							
	
		
			
		
		
	
	
						
					
				
			
			
			Thanks Javier, I've got a lot going on right now, so I'll try to take a look at this next week.
		
		
			No problem at all Kyle,
I will be waiting for your answer and thank you very much for your effort.
Javier
		I will be waiting for your answer and thank you very much for your effort.
Javier
				
				
					Kyle Joseph Stiemann, modified 6 Years ago.
				
				
				
				
					
					
						
							Liferay Master
						
					
					
						
							
							
								Posts: 760
							
						
					
					
						
							Join Date: 1/14/13
						
					
					
						
							
							
							
						
						
							
	
		
			
				
					
						
	
		
	
	
	
		
			Recent Posts
		
	
					
				
				
		
	
						
					
				
				
				
					
						
						
							
	
		
			
		
		
	
	
						
					
				
			
			
			Hi Javier, I got this working by changing your renderer to use the following code:
Either way, let me know if the above code works for you.
- Kyle
		@FacesRenderer(componentFamily = "Test", rendererType = "TestComponent")
public class TestRenderer extends FileUploadRenderer {
    private static final String DOC_LIB_POP_UP_KEY = "docLibPopUp";
    private static final String LIFERAY_DOC_LIB_URL_PLACEHOLDER = "LIFERAY_DOC_LIB_URL";
    private static final String DOC_LIB_POP_UP_SCRIPT_TEMPLATE =
        "AUI().use('liferay-util-window', function(A) {\n" +
        "Liferay.component('" + DOC_LIB_POP_UP_KEY + "', Liferay.Util.Window.getWindow({\n" +
        "dialog: {\n" +
        "centered: true,\n" +
        "constrain2view: true,\n" +
        "resizable: false,\n" +
        "visible: false,\n" +
        "render: true\n" +
        "}\n" +
        "}).plug(A.Plugin.DialogIframe, {\n" +
        "autoLoad: true,\n" +
        "iframeCssClass: 'dialog-iframe',\n" +
        "uri:'" + LIFERAY_DOC_LIB_URL_PLACEHOLDER + "'\n" +
        "}));\n" +
        "});";
    protected void encodeChooseButton(FacesContext context, FileUpload fileUpload, boolean disabled) throws IOException {
        
        PortletRequest request = (PortletRequest) context.getExternalContext().getRequest();
        ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
        long dlScopeGroupId = themeDisplay.getScopeGroupId();
        LiferayPortletURL documentLibURL = PortletURLFactoryUtil.create(request, PortletKeys.DYNAMIC_DATA_MAPPING,
            themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
        try {
            documentLibURL.setWindowState(LiferayWindowState.POP_UP);
            documentLibURL.setPortletMode(PortletMode.VIEW);
        } catch (WindowStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (PortletModeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        documentLibURL.setParameter("struts_action","/dynamic_data_mapping/select_document_library");
        documentLibURL.setParameter("groupId", String.valueOf(dlScopeGroupId));
        
        
        ResponseWriter writer = context.getResponseWriter();
        String clientId = fileUpload.getClientId(context);
        String label = fileUpload.getLabel();
        String cssClass = HTML.BUTTON_TEXT_ICON_LEFT_BUTTON_CLASS + " " + FileUpload.CHOOSE_BUTTON_CLASS;
        cssClass = isValueBlank(label) ? FileUpload.BUTTON_ICON_ONLY + " " + cssClass : cssClass;
        String tabindex = (disabled) ? "-1" : "0";
        if (disabled) {
            cssClass += " ui-state-disabled";
        }
        writer.startElement("span", null);
        writer.writeAttribute("class", cssClass, null);
        writer.writeAttribute("tabindex", tabindex, null);
        writer.writeAttribute("role", "button", null);
        writer.writeAttribute("aria-labelledby", clientId + "_label", null);
        writer.writeAttribute("onclick", "Liferay.component('" + DOC_LIB_POP_UP_KEY + "').show();", null);
        //button icon
        writer.startElement("span", null);
        writer.writeAttribute("class", HTML.BUTTON_LEFT_ICON_CLASS + " ui-icon-plusthick", null);
        writer.endElement("span");
        //text
        writer.startElement("span", null);
        writer.writeAttribute("id", clientId + "_label", null);
        writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);
        if(isValueBlank(label)) {
            writer.write(" ");
        }
        else {
            writer.writeText(label, "value");
        }
        
        writer.endElement("span");
            writer.startElement("div", null);
            writer.writeAttribute("id",  "modal" , null);
            writer.endElement("div");
//        if (!disabled) {
//            encodeInputField(context, fileUpload, clientId);
//        }
        writer.endElement("span");
        writer.startElement("script", null);
        writer.writeAttribute("type", "text/javascript", null);
        writer.write(DOC_LIB_POP_UP_SCRIPT_TEMPLATE.replace(LIFERAY_DOC_LIB_URL_PLACEHOLDER,
            documentLibURL.toString()));
        writer.endElement("script");
    }
}
After looking at the code, I think you might be better off simplifying this component by using a composite component instead (it would be more portable for future versions of PrimeFaces as well). You'd need to disable the default PrimeFaces Upload button onclick behavior with JQuery and replace it with your own, but that's not too difficult.Either way, let me know if the above code works for you.
- Kyle
				
				
					Kyle Joseph Stiemann, modified 6 Years ago.
				
				
				
				
					
					
						
							Liferay Master
						
					
					
						
							
							
								Posts: 760
							
						
					
					
						
							Join Date: 1/14/13
						
					
					
						
							
							
							
						
						
							
	
		
			
				
					
						
	
		
	
	
	
		
			Recent Posts
		
	
					
				
				
		
	
						
					
				
				
				
					
						
						
							
	
		
			
		
		
	
	
						
					
				
			
			
			Also the versions you are using are very old. I'd recommend updating to the latest versions for Liferay 6.2 listed on liferayfaces.org.
- Kyle
		- Kyle
			Hi Kyle,
I am sorry for the delayed answer, I have been working on another things and couldn't test it until yesterday.
It is working now! That's great, thank you very very much Kyle.
About the composite component, the problem is that we are also using the regular fileUpload component, and if I have understand well the composites, it overwrites the regular component, so in this case that wouldn't be possible.
And about the Primefaces version, it is not in my hand to handle this, but I will let it know to the person responsible so we can have an updated version as soon as possible.
I hope with this already working I will be able to finish the component's functionallity.
Thank you one more time for you time Kyle, it has been really helpful
Javier
		I am sorry for the delayed answer, I have been working on another things and couldn't test it until yesterday.
It is working now! That's great, thank you very very much Kyle.
About the composite component, the problem is that we are also using the regular fileUpload component, and if I have understand well the composites, it overwrites the regular component, so in this case that wouldn't be possible.
And about the Primefaces version, it is not in my hand to handle this, but I will let it know to the person responsible so we can have an updated version as soon as possible.
I hope with this already working I will be able to finish the component's functionallity.
Thank you one more time for you time Kyle, it has been really helpful
Javier
				
				
					Kyle Joseph Stiemann, modified 6 Years ago.
				
				
				
				
					
					
						
							Liferay Master
						
					
					
						
							
							
								Posts: 760
							
						
					
					
						
							Join Date: 1/14/13
						
					
					
						
							
							
							
						
						
							
	
		
			
				
					
						
	
		
	
	
	
		
			Recent Posts
		
	
					
				
				
		
	
						
					
				
				
				
					
						
						
							
	
		
			
		
		
	
	
						
					
				
			
			About the composite component, the problem is that we are also using the regular fileUpload component, and if I have understand well the composites, it overwrites the regular component, so in this case that wouldn't be possible.A composite component has almost all the properties of a custom component, so I think you should be able to create a composite component called v:testComponent and replace the onclick functionality of the Upload button using JavaScript. The only reason I recommend this is that it would greatly reduce the lines of code and would also allow you to avoid depending directly on PrimeFaces Java code (which is subject to breaking changes). It would make your code simpler and more future-proof.
It is working now! That's great, thank you very very much Kyle...Glad I could help! Thanks for using Liferay Faces!
Thank you one more time for you time Kyle, it has been really helpful
- Kyle
			Hi Kyle,
I have been taking a look at composite components, but I am not sure on how I would need to do to implement what I want, so I prefer to first finish the work with our already created component and if I have time later, do a bigger research into composites.
So, the last thing that we need to do is to replicate the upload functionality of the fileUpload component, I mean, when I select the desired file, it has to show into the component and the Upload button has to become visible, allowing us to trigger the fileUploadListener.
view.xhtml
I have tried to use the function _166_selectDocumentLibrary(url), which I have seen is the function called when an element of the Doclib is selected, to set the value of the input element used by the FileUploadRenderer as the url of the selected file, but it doesn't seems to work.
I have been searching around to see how FileUploadRenderer does to insert the file into the component and how activate the Upload button, but I can't find it.
I just have added an img element inside the component to test if the function works, but of course it is not valid for our purpose.
I thought you (or someone in the community) may know where is the part where the component is filled with the file, in which case I would really appreciate the help.
I attach the complete example so you can see the whole code.
Thank you very much one more time, I hope I am not abusing of your help.
Javier.
		I have been taking a look at composite components, but I am not sure on how I would need to do to implement what I want, so I prefer to first finish the work with our already created component and if I have time later, do a bigger research into composites.
So, the last thing that we need to do is to replicate the upload functionality of the fileUpload component, I mean, when I select the desired file, it has to show into the component and the Upload button has to become visible, allowing us to trigger the fileUploadListener.
view.xhtml
<p:fileupload fileUploadListener="#{fileUploadView.handleFileUpload}" mode="advanced" update="messages" auto="false" allowTypes="/(\.|\/)(gif|jpe?g|png|jpg)$/" />
<p:growl id="messages" showDetail="true" />    
        
<v:testcomponent fileUploadListener="#{fileUploadView.handleFileUpload}" mode="advanced" update="messages2" auto="false" allowTypes="/(\.|\/)(gif|jpe?g|png|jpg)$/" />
<p:growl id="messages2" showDetail="true" />
FileUploadView.javapublic void handleFileUpload(FileUploadEvent event) {
    //Here goes the code to handle the uploaded file for both of the components
    FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
    FacesContext.getCurrentInstance().addMessage(null, msg);
}I have tried to use the function _166_selectDocumentLibrary(url), which I have seen is the function called when an element of the Doclib is selected, to set the value of the input element used by the FileUploadRenderer as the url of the selected file, but it doesn't seems to work.
I have been searching around to see how FileUploadRenderer does to insert the file into the component and how activate the Upload button, but I can't find it.
I just have added an img element inside the component to test if the function works, but of course it is not valid for our purpose.
    @Override
    protected void encodeAdvancedMarkup(FacesContext context, FileUpload fileUpload) throws IOException {
        .
        .
        .
        writer.startElement("img", null);
            writer.writeAttribute("hspace", "0", null);
            writer.writeAttribute("id", "article-image", null);
            writer.writeAttribute("src", "", null);
            writer.writeAttribute("style", "width:82px;height:83px", null);
            writer.writeAttribute("vspace", "0", null);
        writer.endElement("img");
        .
        .
        .
    }
    
    private static final String INPUT_ID_PLACEHOLDER = "INPUT_ID_PLACEHOLDER";
    private static final String DOC_LIB_POP_UP_SCRIPT_TEMPLATE2 =
            "function _166_selectDocumentLibrary(url) {\r\n" + 
            "        document.getElementById('" + INPUT_ID_PLACEHOLDER + "').value = url;\r\n" + 
            "        var pic1 = document.getElementById(\"article-image\");\r\n" + 
            "        pic1.src = url;" +
            "        Liferay.component('" + DOC_LIB_POP_UP_KEY + "').hide();\r\n" +
            "}";
            
    @Override
    protected void encodeInputField(FacesContext context, FileUpload fileUpload, String clientId) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        inputId = clientId + "_input";
        writer.startElement("input", null);
        writer.writeAttribute("type", "hidden", null);
    //  writer.writeAttribute("type", "file", null);
        writer.writeAttribute("id", inputId , null);
        writer.writeAttribute("name", inputId, null);
        writer.writeAttribute("tabindex", "-1", null);
        if (fileUpload.isMultiple()) writer.writeAttribute("multiple", "multiple", null);
        if (fileUpload.isDisabled()) writer.writeAttribute("disabled", "disabled", "disabled");
        if (fileUpload.getAccept() != null) writer.writeAttribute("accept", fileUpload.getAccept(), null);
        renderDynamicPassThruAttributes(context, fileUpload);
        writer.endElement("input");
    }
I thought you (or someone in the community) may know where is the part where the component is filled with the file, in which case I would really appreciate the help.
I attach the complete example so you can see the whole code.
Thank you very much one more time, I hope I am not abusing of your help.
Javier.
Attachments:
				
				
					Kyle Joseph Stiemann, modified 6 Years ago.
				
				
				
				
					
					
						
							Liferay Master
						
					
					
						
							
							
								Posts: 760
							
						
					
					
						
							Join Date: 1/14/13
						
					
					
						
							
							
							
						
						
							
	
		
			
				
					
						
	
		
	
	
	
		
			Recent Posts
		
	
					
				
				
		
	
						
					
				
				
				
					
						
						
							
	
		
			
		
		
	
	
						
					
				
			
			
			Hi Javier,
I'm not sure I completely understood your initial use-case. I thought you just wanted a PrimeFaces style button to open the Liferay DocLib uploader. However I'm not sure that anything beyond that can be easily accomplished. The current design of your compnonet opens an iframe to upload the file to the DocLib completely outside the JSF lifecycle. I'm not sure there's any way to listen for that upload on the JSF side of things (and the iframe prevents JS interaction on the client-side as well).
I may be missing something, but I think you only have two options:
- Kyle
		I'm not sure I completely understood your initial use-case. I thought you just wanted a PrimeFaces style button to open the Liferay DocLib uploader. However I'm not sure that anything beyond that can be easily accomplished. The current design of your compnonet opens an iframe to upload the file to the DocLib completely outside the JSF lifecycle. I'm not sure there's any way to listen for that upload on the JSF side of things (and the iframe prevents JS interaction on the client-side as well).
I may be missing something, but I think you only have two options:
- Open the DocLib pop up and upload the file there. Then on the backend, obtain the uploaded file from the DocLib to display it in your JSF portlet.
 - Upload the file using normal PrimeFaces upload, and then programmatically add it to the DocLib on the back end. We have an example of this in our PrimeFaces Users Portlet.
 
- Kyle
			Hi Kyle,I think I haven’t explained correctly the use case, I will try to do it:
We are using Primefaces components to insert text and images into a class of our own (in this case a Newsletter). So far, to add images to that newsletter, we are using the fileUpload component to upload an image from the local system into the newsletter. The whole process would be: click choose button, select the image from the local system, it is shown into the fileUpload component, then click the upload button and this triggers the fileUploadListener and in that function we execute the code which add the image into the newsletter.
Now the thing is we want to do the same, but adding an image FROM the docLib (the image is already there) into the newsletter. With our current design, we are able to click the choose button and select an element from the doclib, the problem is once selected, I don’t know if we can replicate the behavior in the original component and see the image into the component and activate the upload button (which would call to the listener and do the same than with the original component).
I don’t know if that is what you meant, but please let me know if I need to clarify something else and if you think this is possible.
Thank you and sorry for the misunderstanding, I hope the purpose of the work is clear now.
Javier.
		We are using Primefaces components to insert text and images into a class of our own (in this case a Newsletter). So far, to add images to that newsletter, we are using the fileUpload component to upload an image from the local system into the newsletter. The whole process would be: click choose button, select the image from the local system, it is shown into the fileUpload component, then click the upload button and this triggers the fileUploadListener and in that function we execute the code which add the image into the newsletter.
Now the thing is we want to do the same, but adding an image FROM the docLib (the image is already there) into the newsletter. With our current design, we are able to click the choose button and select an element from the doclib, the problem is once selected, I don’t know if we can replicate the behavior in the original component and see the image into the component and activate the upload button (which would call to the listener and do the same than with the original component).
I don’t know if that is what you meant, but please let me know if I need to clarify something else and if you think this is possible.
Thank you and sorry for the misunderstanding, I hope the purpose of the work is clear now.
Javier.
				
				
					Kyle Joseph Stiemann, modified 6 Years ago.
				
				
				
				
					
					
						
							Liferay Master
						
					
					
						
							
							
								Posts: 760
							
						
					
					
						
							Join Date: 1/14/13
						
					
					
						
							
							
							
						
						
							
	
		
			
				
					
						
	
		
	
	
	
		
			Recent Posts
		
	
					
				
				
		
	
						
					
				
				
				
					
						
						
							
	
		
			
		
		
	
	
						
					
				
			
			
			Okay, I think I understand what you are trying to do. I'd have to do some research on how to do it though, and I don't really have time right now. Perhaps you can provide a simple JavaScript version of what you are trying to do and ask the same question without reference to JSF in the development or front-end forums. Otherwise, I might be able to take a look at this in the next couple weeks.
		
		
			Hello Kyle.
Sorry again for the delay, I have been out for a few days.
I have been assigned to another tasks so I don't have much time to continue researching about this either, but I will try to ask about this in the front end forums too.
Thank you one more time for your help, I hope we will get a solution soon for this problem.
Javier.
		Sorry again for the delay, I have been out for a few days.
I have been assigned to another tasks so I don't have much time to continue researching about this either, but I will try to ask about this in the front end forums too.
Thank you one more time for your help, I hope we will get a solution soon for this problem.
Javier.