use window.open in an electron app - electron

I'm attempting to open a window from an electron app. Trying to have this opened window node-integration set to false.
const MyButton = (props: any) => {
return props.url ? <a className="my-btn" onClick={() => {
let win = window.open("http://www.google.com/", "_blank", "toolbar=yes,scrollbars=yes,resizable=yes,top=500,left=500,width=400,height=400");
console.log('Is open: ' + !win.closed);
}} target="_blank">My Button</a> : null;
};
Issue is that i don't see the window pop up?

One solution that works is to 'intercept' window.open() calls in the preload script. In the preload script you could create a new browser window and open it.

Related

Failed to add saved page to menu bar - wrapper application using electron

I recently follow a project electron on geeksforgeeks: https://www.geeksforgeeks.org/create-a-geeksforgeeks-wrapper-application-using-electron/
Here is its code on Github https://github.com/sayantanm19/geeksforgeeks-desktop/blob/master/index.js
The function appenItemToMenu doesn't work, which means I could save pages offline but the savedpagelist on menu bar is always empty ...
Could you try it on your machine and point out the bug?
function appendItemToMenu(filename) {
curr_menu = Menu.getApplicationMenu()
.getMenuItemById("saved").submenu
curr_menu.append(
new MenuItem({
label: path.basename(filename, '.html'),
click() {
console.log('Saved page opened')
win.loadFile(savedFolder + path.basename(filename))
}
}))
}
function appendItemToMenu(filename) {
const newMenu = Menu.getApplicationMenu()
curr_menu = newMenu.getMenuItemById('saved').submenu
curr_menu.append(
new MenuItem({
label: path.basename(filename, '.html'),
click() {
console.log('Saved page opened')
win.loadFile(savedFolder + path.basename(filename))
}
}))
Menu.setApplicationMenu(newMenu)
}
Update the application menu after change. Any dynamic change or append Item not allowed.

Electron .ipcRenderer fires twice

I'm creating (for the first time) a small Mac only app using Electron.
I am trying to use ipcRenderer to communicate between my app menu and the content in the main BrowserWindow.
I have the menu set up as follows to send the message 'select-active':
const {Menu} = require('electron')
const electron = require('electron')
const app = electron.app
const BrowserWindow = electron.BrowserWindow
const template = [
{
label: 'Fonts',
submenu: [
{
label: 'Select All Acitve Fonts',
accelerator: 'Command+A',
click (item, focusedWindow) { if(focusedWindow) focusedWindow.webContents.send('select-active') }
},...
which I am then receiving as follows:
const ipcRenderer = require('electron').ipcRenderer;
ipcRenderer.on('select-active', function () {
console.log('SELECTED');
})
The problem I have is that every time the menu command is selected the message is logged twice in the console. Where am I going wrong?
How about using .once instead
ipcRenderer.once('select-active', function () {
console.log('SELECTED');
})
You are subscribing to ipcRenderer.on after React component rerendering (React calls your function every time it needs to get rendered version of it). Try to define the ipcRenderer.on event handler outside of React component function.
function yourFunction(){
return(){}
}
export default yourFunction;
ipcRenderer.send();
Place your ipcRenderer.send(); under the export default yourFunction;
It`s works for me!

Can't open Electron webview links with target = blank

I'm using Electron I have a webview which display an external website but I can't succeed to show the additional window normally opened by links on this site and which have target = _blank.
Mentions légales
I tried with
webpreferences="nativeWindowOpen=yes" allowpopups
But it didn't change.
With a webview, you can actually handle these on the main process quite easily.
Which also allows you to disable nodeIntegration should that be a requirement.
// Listen for web contents being created
app.on('web-contents-created', (e, contents) => {
// Check for a webview
if (contents.getType() == 'webview') {
// Listen for any new window events
contents.on('new-window', (e, url) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
After digging into the documentation I wrote this code (code located in the renderer):
const {BrowserWindow} = require('electron').remote
..........
webview1.addEventListener('new-window', (e) => {
const protocol = require('url').parse(e.url).protocol
if (protocol === 'http:' || protocol === 'https:') {
//shell.openExternal(e.url)
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL(e.url);
}
})
The line shell.openExternal(e.url) open the url of the link in a tab of the default browser.
And by using a new BrowserWindow, the new windows are Electron Window.

Electron Framework - TypeError: Cannot read property 'exec' of undefined

I am new to Electron Framework and I am trying out an application where I need to launch a particular software (e.g. firefox) on a menu item click in my app.
Right now I am trying to build the app on Windows platform (using Windows 7).
Use case
- Home page with static content
- Application menu on top with 'Launch my software' as a menu item
- On click of this menu item I want to launch a software which is installed on my system (I know the path to the exe file)
Steps to create and start the project
npm init (to enter the details of the project and create package.json)
npm install electron --save-dev --verbose
created main.js and main.html (simple HTML file with a header) as mentioned below
npm start
Contents of main.js as follows
const electron = require('electron');
const app = electron.app;
const { Menu } = require('electron');
const BrowserWindow = electron.BrowserWindow;
var childProc = electron.ChildProcess;
var mainWindow;
const menu = Menu.buildFromTemplate([
{
label: 'Menu',
submenu: [{
label: 'Launch my Software',
click: function () {
var child = childProc.exec;
var executablePath = "<path to executable for the software>";
child(executablePath, function(err, data) {
if (err) {
console.error(err);
return;
}
console.log(data.toString());
});
}
}]
}
]);
Menu.setApplicationMenu(menu);
function createWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600
});
mainWindow.loadURL('file://' + __dirname + '/main.html');
mainWindow.setMenu(menu);
mainWindow.on('closed', () => {
mainWindow = null;
});
}
app.on('ready', createWindow);
app.on('activate', () => {
if (mainWindow == null) {
createWindow();
}
});
After doing npm start, the project is launched. But when I click on the menu item to launch my software, I get the following error
Uncaught Exception:
TypeError: Cannot read property 'exec' of undefined
and it is pointing at line no. 18
var child = childProc.exec;
I went through different posts and tried out the suggestions but it has not worked for me. Can anyone pls help on this.
Thanks in advance.
Electron doesn't have a ChildProcess method or property.
If you want to exec a command then use;
const childProcess = require('child_process')
childProcess.exec('')

Communicate with <webview> in Electron

I have a <webview> in my Electron app. I'd like to have safe "foreign" communication, the way I would with an iframe through postMessage. So for example:
webview.executeJavaScript("window.parent.postMessage('all done!')");
Is my only choice for communication with this subwebview to turn on nodeIntegration so that I can use sendToHost? Turning on all of nodeIntegration just for this one feature seems like overkill.
You can access Electron APIs in the webview preload script, including IPC, even when nodeIntegration is disabled. Your preload script can inject functions into the global namespace that will then be accessible within the page loaded in the webview. A simple example:
webview-preload.js:
const { ipcRenderer } = require('electron')
global.pingHost = () => {
ipcRenderer.sendToHost('ping')
}
webview-index.html:
<script>
pingHost()
</script>
window-index.html:
<script>
const webview = document.getElementById('mywebview')
webview.addEventListener('ipc-message', event => {
// prints "ping"
console.log(event.channel)
})
</script>
Easiest way
Communication is
Note:
(main.js or app.js or background.js or process.js ) no need to pass (directly pass component to component),i succesffully implemented in electron:3.1.10
for print html webview.
Window To Webview
example1.html
<webview id="paper" style="width:300px;height:800px" src="file:///static/mywebview.html" nodeintegration></webview>
example1.js
var webview = document.getElementById("paper");
webview.send("ping",data);
getting data from mycomponent or window(i send directly form component)
mywebview.html
<!---what data you want show----!>
mywebview.js
const {
ipcRenderer
} = require('electron')
//data from window
ipcRenderer.on('ping', (e, data) => { console.log(data) })
webview to window
Webview to window(direct pass to component)
mywebview.js
ipcRenderer.sendToHost("readyCompanyInfo",data)
in my window eg i use vue (mycomponent.vue or mypage)
example1.html
const ipcRenderer = require("electron").ipcRenderer;
webview.addEventListener("ipc-message",(event)=>{
const {args,channel}=event;
if(channel=="readyCompanyInfo")
{
console.log(channel,args)
//here you can see data what u passed from webview to window
console.log(args[0])
}
})

Resources