So, I am pretty new to Electron and wanted to build a desktop application. But I have been running into issues, particularly in getting the renderer and main processes to communicate. I am aware of the IPC and remote concepts and this about me not being able to use them in the first place. I have tried to surf through a lot of related questions before deciding to post here. To be more specific, I have a form(HTML) that needs to be filled out and saved to a local database(sqlite) which I originally planned to access from within the HTML but couldn’t. Therefore, I went for a renderer.js and included that as a script to the HTML, which also failed(couldn’t use ‘require’)- I had nodeintegration turned on during both times. Here are the other solutions tried with no luck so far:
A preload.js script : From what I imagined, I would be able to include my ‘require’ statements here but the problem came when I tried to access DOM elements since I had to register the IPC events
I finally went for the browserify tool after learning that it could bundle all necessary modules and make them available to the renderer. Here too, I followed the procedures stated (https://github.com/browserify/browserify#usage), but just couldn’t get it to work with a whole bunch of new errors being thrown (TypeError: fs.existsSync is not a function, RangeError) and I am still getting the dreaded ‘require’ is not defined error in the browser.
I am basically at an impasse now and don’t know where to go from here. I can share some code here if necessary. Any help will be greatly appreciated.
main.js
const MainDAO = require('./dao/appDAO')
const {ipcMain} = require('electron')
const electron = require('electron')
const { app, BrowserWindow, Menu } = require('electron')
const path = require('path')
//const template = require('./js/templates')
//const employeeReg = require('./assets/js/employeeReg')
const dbPath = 'Model/lunaDb'
const dialog = electron.dialog
let lunaDB = new MainDAO(dbPath);
/************************************************************************** */
/*************Login Page
****************************************************************************/
function createSignInWindow() {
// Create the browser window.
let signIn = new BrowserWindow({
width: 800, height: 520, icon: __dirname + '/img/logo.png',
webPreferences: {
nodeIntegration: true,
}
});
//Load signin window
signIn.loadFile('view/signin.html')
//remove menu list
signIn.removeMenu();}
register.html: This is where I first wanted to save form data to sqlite database
<script src="../dist/bundle.js"></script>
<script>
var currentTab = 0; // Current tab is set to be the first tab (0)
showTab(currentTab); // Display the current tab
function showTab(n) {
// This function will display the specified tab of the form ...
var x = document.getElementsByClassName("tab");
x[n].style.display = "block";
// ... and fix the Previous/Next buttons:
if (n == 0) {
document.getElementById("prevBtn").style.display = "none";
} else {
document.getElementById("prevBtn").style.display = "inline";
}
if (n == (x.length - 1)) {
document.getElementById("nextBtn").innerHTML = "Submit And Again";
} else {
document.getElementById("nextBtn").innerHTML = "Next";
}
// ... and run a function that displays the correct step indicator:
fixStepIndicator(n)
}
function nextPrev(n) {
// This function will figure out which tab to display
var x = document.getElementsByClassName("tab");
// Exit the function if any field in the current tab is invalid:
if (n == 1 && !validateForm()) return false;
// Hide the current tab:
x[currentTab].style.display = "none";
// Increase or decrease the current tab by 1:
currentTab = currentTab + n;
// if you have reached the end of the form... :
if (currentTab >= x.length) {
window.location.reload();
//...the form gets submitted:
alert("Succesfully Added");
// document.getElementById("regForm").submit();
return false;
}
// Otherwise, display the correct tab:
showTab(currentTab);
}
function validateForm() {
// This function deals with validation of the form fields
var x, y, i, valid = true;
x = document.getElementsByClassName("tab");
z = x[currentTab].getElementsByClassName("needs-validation");
y = x[currentTab].getElementsByTagName("input");
var validation = Array.prototype.filter.call(z, function (form) {
form.classList.add("was-validated");
switch (currentTab) {
case 0:
var name = document.querySelector('#inputName');
var email = document.querySelector('#inputEmail');
var phone = document.querySelector('#inputPhoneNo')
if ((email.checkValidity() == false) || (name.checkValidity() == false) || (name.checkValidity() == false)) {
valid = false;
}
break;
case 1:
var name = document.querySelector('#inputContactName');
var phone = document.querySelector('#inputContactPhoneNo');
if ((name.checkValidity() == false) || (phone.checkValidity() == false)) {
valid = false;
}
break;
case 2:
var position = document.querySelector('#inputPosition');
var salary = document.querySelector('#inputBasicSalary');
var hiringDate = document.querySelector('#inputHiringDate')
if ((position.checkValidity() == false) || (salary.checkValidity() == false) || (hiringDate.checkValidity() == false)) {
valid = false;
}
break
default:
break;
}
});
if (valid) {
document.getElementsByClassName("step")[currentTab].className += " finish";
}
return valid; // return the valid status
}
function fixStepIndicator(n) {
// This function removes the "active" class of all steps...
var i, x = document.getElementsByClassName("step");
for (i = 0; i < x.length; i++) {
x[i].className = x[i].className.replace(" active", "");
}
//... and adds the "active" class to the current step:
x[n].className += " active";
}
</script>
<script src="../assets/js/register.js"></script>
register.js(renderer): require is not defined
const ipc = require('electron').ipcRenderer
const submitEmplForm = document.getElementById('nextBtn')
preload.js : when i try to access the DOM components here, it complains of being null that is why I tried adding the require(‘./register)…that didn’t work either
const { ipcRenderer } = require('electron')
const emp = require('./register')
const _setImmediate = setImmediate
const _clearImmediate = clearImmediate
process.once('loaded', () => {
global.setImmediate = _setImmediate
global.clearImmediate = _clearImmediate
})
const submitEmplForm = document.querySelector('nextBtn')
submitEmplForm.addEventListener('click', function (event) {
ipcRenderer.send('asynchronous-message', 'ping')
})
ipcRenderer.on('asynchronous-message', function (event, args) {
event.preventDefault()
console.log('event is ' + event)
console.log(args)
})
There is also of course the bundle.js file from browserify.
Advertisement
Answer
I finally managed to access the required modules and the DOM elements from within the renderer.js file after carefully creating a new file, starting out with the bare minimum and adding more code incrementally to isolate where the problem was. To be perfectly honest, I did not do anything much differently other than get rid of the preload script, turn on nodeIntegration again and like I mentioned, create a new renderer file and link that to the HTML as the script. That did the trick and now the main and UI can communicate through IPC. Since this is merely a desktop application, I am hoping any security issues associated with turning on nodeIntegration won’t be much of a problem.