Cannot get my main and renderer processes to communicate in electron



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:

  1. 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

  2. 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.

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.



Source: stackoverflow