Managing digital assets in Liferay’s Document and Media Library can be straightforward, but accessing the folder structure programmatically can add even more flexibility to your site. This guide will walk you through how to access, display, and manage folders and documents in Liferay using both FreeMarker and the Headless API. By the end, you’ll have a dynamic, navigable document tree structure for your site.
Table of Contents
Step 1: Creating and Organizing Folders and Documents
Before we dive into the code, make sure to create a folder structure in the Document and Media Library:
- Go to the Document and Media section in the Liferay admin panel.
- Create a new folder, and add some documents and subfolders within it.
- Keep track of your folder hierarchy, as we’ll be using this structure in the code later.
Step 2: Accessing the Root Folder with a Widget Template
We’ll start by creating a Widget Template to fetch the root folder. This template will help us identify and work with the root folder ID dynamically using FreeMarker.
Create a New Widget Template:
- Go to Left Product Menu > Design > Templates.
- Click on Widget Templates Tab.
- Click Add, and choose the Media Gallery widget.
- Insert the following FreeMarker code to extract the root folder ID from the portlet preferences:
<#assign rootFolder = "" />
<#list portletPreferences?keys as preference>
<#if portletPreferences[preference]??>
<#assign mapValues = portletPreferences[preference] />
<#list mapValues as value>
<#if preference == "rootFolderId">
<#assign rootFolder = value />
</#if>
</#list>
</#if>
</#list>
This snippet dynamically assigns the root folder ID to the rootFolder
variable, which we’ll use in the upcoming steps.
Also Read: How to Use FreeMarker Template(FTL) in widget Template
HTML Structure for the Tree:
Include the following HTML code in your template to set up a container for displaying the folder structure:
<div class="tree"></div>
Step 3: Fetching Subfolders Using the Headless API
With the root folder ID ready, we can use Liferay’s Document Folder Headless API to fetch all subfolders within the root folder. Below is a jQuery script that makes an AJAX call to retrieve these subfolders:
$(document).ready(function() {
let rootFolderId = ${rootFolder};
let rootUl = $('<ul class="first-node px-0"></ul>');
$.ajax({
url: '/o/headless-delivery/v1.0/document-folders/' + rootFolderId + '/document-folders?flatten=true',
type: 'GET',
dataType: 'json',
headers: {
"accept": "application/json",
"x-csrf-token": Liferay.authToken
},
success: function(documentFolderData) {
let items = documentFolderData.items || [];
items.forEach(function(item) {
if (item.id == rootFolderId) {
let folderName = item.name;
fetchDocumentsAndFolders(rootFolderId, folderName, rootUl);
}
});
}
});
$('.tree').append(rootUl);
});
Explanation:
rootFolderId
: This variable holds the ID of the root folder fetched from the Widget Template.- The AJAX call retrieves all document folders under the root using Liferay’s Headless API.
- The
fetchDocumentsAndFolders
function is called to populate the folder contents, which we’ll define next.
Step 4: Fetching Documents and Nested Folders
Now, let’s define a function to recursively fetch documents and child folders, building out the entire folder structure.
function fetchDocumentsAndFolders(folderId, folderName, parentUl) {
let folderLi = $('<li></li>');
let folderSpan = $('<div class="h6">'+ folderName +'</div>');
folderLi.append(folderSpan);
parentUl.append(folderLi);
let documentsUl = $('<ul></ul>');
folderLi.append(documentsUl);
// Fetch documents inside the current folder
$.ajax({
url: '/o/headless-delivery/v1.0/document-folders/' + folderId + '/documents',
type: 'GET',
dataType: 'json',
headers: {
"accept": "application/json",
"x-csrf-token": Liferay.authToken
},
success: function(documentsData) {
let items = documentsData.items || [];
items.forEach(function(item) {
let documentLi = $('<li><a href="' + item.contentUrl + '"><div class="h6">' + item.fileName + '</div></a></li>');
documentsUl.append(documentLi);
});
}
});
// Fetch child folders of the current folder
$.ajax({
url: '/o/headless-delivery/v1.0/document-folders/' + folderId + '/document-folders',
type: 'GET',
dataType: 'json',
headers: {
"accept": "application/json",
"x-csrf-token": Liferay.authToken
},
success: function(responseData2) {
let childItems = responseData2.items || [];
childItems.forEach(function(childItem) {
fetchDocumentsAndFolders(childItem.id, childItem.name, documentsUl);
});
}
});
}
Explanation:
- This function first fetches all the documents within the given folder (
folderId
) and appends them to thedocumentsUl
list. - It then makes a second AJAX call to retrieve the subfolders and calls itself recursively to display each subfolder’s content.
Step 5: Setting Up the Media Gallery on Your Page
To implement the media gallery:
- Drag and drop the Media Gallery widget onto your page.
- Select the appropriate widget template (the one you created earlier).
- Choose the root folder from the Document and Media library.
- Click Save and Publish the page.
- Verify that the folder and document structure displays correctly.
Conclusion
With these steps, you should be able to set up a dynamic document gallery that can display and navigate through nested folders and documents. This approach can be extended by adding features like search, permissions management, and custom filtering.
For more advanced integrations, check out our related article on using Liferay’s API Builder: Liferay API Builder Guide.