Nextcloud Files helpers for Nextcloud apps and libraries.
This library provides three kinds of utils:
- WebDAV helper functions to work with the Nextcloud WebDAV interface.
Those functions are available in
@nextcloud/files/dav - Geneal purpose function related to files or folders, like filename validation.
- Functions and classes to interact with the Nextcloud files app, like registering a new view or a file action.
@nextcloud/files version | Supported | Nextcloud version |
|---|---|---|
| 4.x | ✅ | 33+ |
| 3.x | ✅ | 26-32 |
| 2.x | ❌ | 23-25 |
| 1.x | ❌ | 20-22 |
The "New"-menu allows to create new entries or upload files, it is also possible for other apps to register their own actions here.
importtype{Entry}from'@nextcloud/files'import{addNewFileMenuEntry}from'@nextcloud/files'import{t}from'@nextcloud/l10n'constmyEntry: Entry={// unique ID of the entryid: 'my-app',// The display name in the menudisplayName: t('my-app','New something'),// optionally pass an SVG (string) to be used as the menu entry iconiconSvgInline: importedSVGFile,handler(context: Folder,content: Node[]): void{// `context` is the current active folder// `content` is the content of the currently active folder// You can add new files here e.g. use the WebDAV functions to create files.// If new content is added, ensure to emit the event-bus signals so the files app can update the list.}}addNewFileMenuEntry(myEntry)It is possible to provide your own sidebar tabs for the files app. For this you need to create a custom web component, which can either be done without any framework by using vanilla JavaScript but is also possible with Vue.
This example will make use of the Vue framework for building a sidebar tab as this is the official UI framework for Nextcloud apps.
The sidebar tab consists of two parts:
- The web component which will be rendered within the sidebar.
- A definition object that provides all information needed by the files app.
This object provides the requires information such as:
- The order (to ensure a consistent tabs order)
- The display name for the tab navigation
- An icon, to be used in the tab navigation
- A callback to check if the sidebar tab is enabled for the current node shown in the sidebar.
- The web component tag name
The registration must happen in an initScript.
importtype{ISidebarTab}from'@nextcloud/files'import{getSidebar}from'@nextcloud/files'import{t}from'@nextcloud/l10n'constMyTab: ISidebarTab={// Unique ID of the tabid: 'my_app',// The display name in the tab listdisplayName: t('my_app','Sharing'),// Pass an SVG (string) to be used as the tab button iconiconSvgInline: '<svg>...</svg>',// Lower values mean a more prominent positionorder: 50,// The tag name of the web componenttagName: 'my_app-files_sidebar_tab',// Optional callback to check if the tab should be shownenabled({ node, folder, view }){// you can disable this tab for some cased based on: // - node: The node the sidebar was opened for // - folder: The folder currently shown in the files app // - view: The currently active files view returntrue},// Optional, recommended to large tabs asynconInit(){// This is called when the tab is about to be activated the first time. // So this can be used to do some initialization or even to define the web component. },}// the you need to register it in the sidebargetSidebar().registerTab(MyTab)The web component needs to have those properties:
- node of type
INode - folder of type
IFolder - view of type
IView - active of type
boolean
When using Vue you need to first create the Vue component:
<script setup lang="ts">importtype { IFolder, INode, IView } from'@nextcloud/files'defineProps<{ node:INode folder:IFolder view:IView active:boolean}>()</script>
<template>
<div>
<div>Showing node: {{ node.source }}</div>
<div>... in folder: {{ folder.source }}</div>
<div>... with view: {{ view.id }}</div>
</div>
</template>Which then can be wrapped in a web component and registered.
import{getSidebar}from'@nextcloud/files'import{defineAsyncComponent,defineCustomElement}from'vue'getSidebar().registerTab({// ...tagName: `my_app-files_sidebar_tab`,onInit(){constMySidebarTab=defineAsyncComponent(()=>import('./views/MySidebarTab.vue'))// make sure to disable the shadow root to allow theming with Nextcloud provided global styles.constMySidebarTabWebComponent=defineCustomElement(MySidebarTab,{shadowRoot: false})customElements.define('my_app-files_sidebar_tab',MySidebarTabWebComponent)},})The getClient exported function returns a webDAV client that's a wrapper around webdav's webDAV client.
All its methods are available here.
import{getClient,defaultRootPath,getFavoriteNodes}from'@nextcloud/files/dav'constclient=getClient()// query favorites for the root folder (meaning all favorites)constfavorites=awaitgetFavoriteNodes(client)// which is the same as writing:constfavorites=awaitgetFavoriteNodes(client,'/',defaultRootPath)import{getClient,getDefaultPropfind,resultToNode,defaultRootPath,defaultRemoteURL}from'@nextcloud/files/dav'// Get the DAV client for the default remoteconstclient=getClient()// which is the same as writingconstclient=getClient(defaultRemoteURL)// of cause you can also configure another WebDAV remoteconstclient=getClient('https://example.com/dav')constpath='/my-folder/'// the directory you want to list// Query the directory content using the webdav library// `davRootPath` is the files root, for Nextcloud this is '/files/USERID', by default the current user is usedconstresults=client.getDirectoryContents(`${defaultRootPath}${path}`,{details: true,// Query all required properties for a Nodedata: getDefaultPropfind()})// Convert the result to an array of Nodeconstnodes=results.data.map((result)=>resultToNode(r))// If you specified a different root in the `getDirectoryContents` you must add this also on the `resultToNode` call:constnodes=results.data.map((result)=>resultToNode(r,myRoot))// Same if you used a different remote URL:constnodes=results.data.map((result)=>resultToNode(r,myRoot,myRemoteURL))import{getClient,getDefaultPropfind,resultToNode,defaultRootPath,}from'@nextcloud/files/dav'import{emit}from'@nextcloud/event-bus'constclient=getClient()client.stat(`${defaultRootPath}${filename}`,{details: true,data: getDefaultPropfind(),}).then((result)=>{constnode=resultToNode(result.data)emit('files:node:updated',node)})