What's the proper way to handle forms in Electron?

前端 未结 3 1384
野趣味
野趣味 2021-02-11 19:48

The form html and submit event is part of the \"renderer\". The submitted data should be available in the main process. What\'s the proper way to submit the form and make that d

3条回答
  •  醉话见心
    2021-02-11 20:15

    There are several variations on how to do this, but all are via IPC. 

    IPC (inter process communication) is the only way to get data from the render process to the main process, and is event driven. The way this works is that you can use custom defined events which the process listens for and returns something when that event happens.

    The example stated by @Adam Eri is a variation on the ipcMain example found in the documentation, but this method is not one size fits all.

    The reason for saying that is the matter can quickly become complicated if you are trying to send events via the menu (which typically runs on the main process), or via components through a front end framework like Vue or Angular.

    I will give a few examples:

    Using Remote with WebContents

    To your point, yes you can use electron remote, but for the purposes of forms it is not the recommended approach. Based on the documentation, the point of remote is to 

    Use main process modules from the renderer process

    tl:dr -This process can cause deadlocks due to its synchronous nature, can cause event object leaks (due to garbage collection), and leads to unexpected results with callbacks.

    Further explanation can be had from the documentation but ultimately this is set for using items like dialog and menu in the render process.

    index.js (main process)

    const { app, BrowserWindow, ipcMain } = require('electron');
    const path = require ('path');
    const fs = require('fs');
    const os = require('os');
    
    let window;
    
    function createWindow(){
        window = new BrowserWindow({
            show: false
        });
    
        window.loadURL(`file://${__dirname}/index.html`);
        window.once('ready-to-show', function (){
            window.show();
        });
    
        window.webContents.openDevTools();
    
        let contents = window.webContents;
    
        window.on('closed', function() {
            window = null;
        });
    }
    
    exports.handleForm = function handleForm(targetWindow, firstname) {
        console.log("this is the firstname from the form ->", firstname)
        targetWindow.webContents.send('form-received', "we got it");
    };
    
    app.on('ready', function(){
        createWindow();
    });
    

    index.html

    
    
        
            
            Electron App
        
    
        
    
            
    First name:

    Last name:


    renderFile.js (Render Process)

    const { remote, ipcRenderer } = require('electron');
    const { handleForm} = remote.require('./index');
    const currentWindow = remote.getCurrentWindow();
    
    const submitFormButton = document.querySelector("#ipcForm2");
    const responseParagraph = document.getElementById('response')
    
    submitFormButton.addEventListener("submit", function(event){
            event.preventDefault();   // stop the form from submitting
            let firstname = document.getElementById("firstname").value;
            handleForm(currentWindow, firstname)
    });
    
    ipcRenderer.on('form-received', function(event, args){
        responseParagraph.innerHTML = args
        /*
            you could choose to submit the form here after the main process completes
            and use this as a processing step
        */
    });
    

    Traditional IPC

    index.js (Main Process)

    const { app, BrowserWindow, ipcMain } = require('electron');
    const path = require ('path');
    const fs = require('fs');
    const os = require('os');
    
    let window;
    
    function createWindow(){
        window = new BrowserWindow({
            show: false
        });
    
        window.loadURL(`file://${__dirname}/index.html`);
        window.once('ready-to-show', function (){
            window.show();
        });
    
        window.webContents.openDevTools();
    
        let contents = window.webContents;
    
        window.on('closed', function() {
            window = null;
        });
    }
    
    ipcMain.on('form-submission', function (event, firstname) {
        console.log("this is the firstname from the form ->", firstname)
    });
    
    app.on('ready', function(){
        createWindow();
    });
    

    index.html

    
    
        
            
            Electron App
        
    
        
    
            
    First name:

    Last name:


    renderFile.js (Render Process)

    const ipcRenderer = require('electron').ipcRenderer;
    
    function sendForm(event) {
        event.preventDefault() // stop the form from submitting
        let firstname = document.getElementById("firstname").value;
        ipcRenderer.send('form-submission', firstname)
    }
    

    Using WebContents

    A possible third option is webContents.executeJavascript to access the renderer process from the main process. This explanation from the remote documentation section.

    Summary

    As you can see, there are a few options on how to handle forms with Electron. So long as you use IPC, you should be fine; its just how you use it that can get you into trouble. I have shown plain javascript options for handling forms, but there are countless ways to do so. When you bring a front end framework into the mix, it gets even more interesting.

    I personally use the traditional IPC approach when I can.

    Hope that clears things up for you!

提交回复
热议问题