{{announcement.body}}
{{announcement.title}}

Electron With Typescript - File Explorer Desktop App

DZone 's Guide to

Electron With Typescript - File Explorer Desktop App

In this article, we demonstrate how to create a file explorer application with Electron and Typescript.

· Web Dev Zone ·
Free Resource

The Electron library is easy to use for native desktop applications with the knowledge of web technologies. If you're new to Electron and need an introduction, check out this article.

In this article, we are going to create a native file explorer with the ability to view multiple folders or files at once. We will be using TypeScript on top of the Electron library.

Getting Started

We can start with a template project from this github repository.Just clone the project and run the following commands: 

npm install 
 npm start 

This will start our application and display a browser window that displays the version of Node and Electron that we have running.

Now, we will add a button to open the native folder dialog and an input button to show the selected folders and files (index.html).

HTML




x


 
1
<label class="padding20">Folders: </label>
2
<input id="selectedfolders" class="inputtextwidth" type="text" 
3
          placeholder="Selected folders paths displayed here.." disabled>
4
<button class="inlinedisplay margin20" id="folderchooser">Choose folder to list files</button>


 
 

In renderer.ts, we have a button handler to send the channel using ipcRenderer.

JavaScript




xxxxxxxxxx
1


 
1
    btn.addEventListener("click", (ev: Event) => {
2
        ipcRenderer.send("showFolderDialog");
3
    });


  

You may also like: What Is Electron and Why Should We Use it?

In main.ts, the showfolderdialog channel listened and then opened the dialog. The dialog will be provided by Electron,  which has properties like openfile and opendirectory with multi-selections. 

Then, when the promise executes, we get the selected file paths, which map the file path to read directory and gets all the files inside the directory. This, we again send to the reduce function to get the statistics of the of files. It will send the files with statistics sent through the channel, filelist.

The reduce function is to combine all the files of different folders to make one single list.

We also send the file paths separately by sending the selectedfolders to display the folders path in the input box.
 

JavaScript




xxxxxxxxxx
1
19


 
1
  ipcMain.on("showFolderDialog", (event: IpcMainEvent) => {
2
    let fileSelectionPromise = dialog.showOpenDialog({properties: ["openFile", "openDirectory", "multiSelections"]});
3
    fileSelectionPromise.then(function(obj) {
4
        event.sender.send("selectedfolders", obj.filePaths);
5
        let cumfileslist = obj.filePaths.map((filePath, index)=>{
6
          return fs.readdirSync(filePath, {withFileTypes: true})
7
                   .filter(dirent=>!dirent.isDirectory())
8
                   .map(dirent=>filePath + "/" + dirent.name);
9
        }).reduce((filesacc, files) => {
10
            filesacc = filesacc.concat(files);
11
            return filesacc;
12
        }).every((absolutefilepath, index, array) => {
13
          let stats:fs.Stats = fs.statSync(absolutefilepath);
14
          event.sender.send("fileslist", path.basename(absolutefilepath), stats);
15
          return true;
16
        });
17
    });
18
  });
19
 
          


    

In renderer.ts,  selectedfolders is used to create an event listener to get all the file paths and then concatenate them with the pipe symbol and place it in the value.

JavaScript




xxxxxxxxxx
1


 
1
ipcRenderer.on("selectedfolders", (evt: IpcRendererEvent, selectedfolders: string[]) => {
2
    const selectedFolderElem: HTMLInputElement = document.getElementById("selectedfolders") as HTMLInputElement;
3
    selectedFolderElem.value = selectedFolderElem.value !== "" ? selectedFolderElem.value + "|"
4
                                                            : selectedFolderElem.value ;
5
    selectedFolderElem.value += selectedfolders.join(" | ");
6
});
7
 
          


 
 

To list all the files, we can have an ul element and template element that can be expanded for each file display.

HTML




xxxxxxxxxx
1
13


 
1
<div>
2
      <ul id="filelist" class="nopadding">
3
      </ul>
4
    </div>
5
    <template id="filerec">
6
      <div class="row">
7
          <li class="grid-container">
8
              <span></span>
9
              <span>234234</span>
10
              <span>234</span>
11
          </li>
12
      </div>
13
    </template>


 
 

In renderer.ts, it will listen on the  filelist element, which receives the parameters (filename, stats) and fill all the template span elements. Then, the template is cloned and added to the ul element.

JavaScript




xxxxxxxxxx
1
11


 
1
ipcRenderer.on("fileslist", (event: IpcRendererEvent, fileName: string, stats: fs.Stats) => {
2
    const filetemplate = document.getElementById("filerec") as HTMLTemplateElement;
3
    const filedisplayrec = filetemplate.content;
4
    const spanElements = filedisplayrec.querySelectorAll("span");
5
    spanElements[0].innerText = fileName;
6
    spanElements[1].innerText = stats.size.toString();
7
    spanElements[2].innerText = stats.mtime.toString();
8
    const nodeElement: Node = filedisplayrec.cloneNode(true);
9
    document.getElementById("filelist").appendChild(nodeElement);
10
});
11
 
          


 
 

The desktop app will finally look like this. The full source code is available on github for reference

 

 

Further Reading

Topics:
electron ,typescript ,desktop app framework ,desktop app

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}