Reputation: 33
I am trying to send lightmode and language data through ipcMain to ipcRenderer through my preload script:
Preload.js:
const { contextBridge, ipcRenderer } = require("electron");
const ipc = {
render: {
send: ["mainMenuUpdate"],
receive: ["windowStats"],
},
};
contextBridge.exposeInMainWorld("ipcRender", {
// From render to main.
send: (channel, args) => {
let validChannels = ipc.render.send;
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
},
// From main to render.
receive: (channel, args) => {
let validChannels = ipc.render.receive;
if (validChannels.includes(channel)) {
ipcRenderer.on(channel, args);
}
},
});
I send the data like this:
mainMenu.js:
window.ipcRender.send('mainMenuUpdate', {
// windowSkin and currentLanguage are both coming from the previous window update
// and are an object with hexvalues and string respectively. Doesn't matter in this
// case
currentSkin: windowSkin,
currentLanguage,
})
Note that this has been working for all other windows I have updated but not this one.
I recieve this no problem in main.js
as follows:
ipcMain.on('mainMenuUpdate', (event, args) => {
console.log(args);
// outputs correcly
mainWindow.webContents.send("windowStats", args);
});
and then sends it away through windowStats
to myPage.js
:
let currentLanguage;
let windowSkin;
window.ipcRender.receive("windowStats", (event, windowArgs) => {
console.log(windowArgs);
// does not output anything because of double error
windowSkin = windowArgs.currentSkin;
currentLanguage = windowArgs.currentLanguage;
updateColors(windowArgs.currentSkin);
langUpdate(currentLanguage);
});
I get a log when sending it from mainMenu.js
, I get the same log when received in main.js
, just before I send it with mainWindow.webcontents.send(//...)
but no log because of the error.
Uncaught TypeError: Cannot read properties of undefined (reading 'receive') at myPage.js:18:18 (anonymous @ myPage.js:18)
I get this two times, exactly the same error if that would help. I have also tried to load in the new html file both before and after I send it through IPC.
The myPage.html
looks as follows:
<body>
<main class="main-container">
<section class="left-column">
<div class="my-library-container">
<div class="left-column-btns myLibrary-btn" data-translation-key data-string="myPage:myLibrary-btn">??MY
LIBRARY
</div>
</div>
<div class="collections-container">
<div class="left-column-btns collections-btn" data-translation-key data-string="myPage:collections-btn">
??COLLECTIONS</div>
</div>
</section>
<section class="main-column">
<iframe class="main-screen" src="../myPage/myLibrary.html" frameborder="0"></iframe>
</section>
<section class="right-column"></section>
</main>
<script defer src="../../assets/js/myPage/myPage.js"></script>
<script defer src="../../constants/colors.js"></script>
<script defer src="../../constants/languages.js"></script>
</body>
which I show inside an iframe
like this:
<body>
<main class="main-container">
<iframe class="main-window" src="myPage/myPage.html" frameborder="0"></iframe>
</main>
<script defer src="../assets/js/mainMenu.js"></script>
<script defer src="../constants/colors.js"></script>
<script defer src="../constants/languages.js"></script>
</body>
What may or may not contribute to the problem is that it seems like the javascript is loaded before the HTML even when JS file is deferred.
myPage.js
ex.
const myLibraryBtn = document.querySelector('.myLibrary-btn')
myLibraryBtn.classList.add('activated')
and get this error:
Uncaught TypeError: Cannot read properies of null (reading 'classList') at ...
I will happily elaborate and extend this question because I have no idea what I even should look for and where.
UPDATE:
As I've been doing excessive testing I have concluded that I can't get anything through the ipc (main --> renderer) while the renderer is an iframe
. I can put in a button to update the window normally without iframe
, even though I still get a
Uncaught TypeError: Cannot read properties of undefined (reading 'receive') at myPage.js....
error. But it doesn't seem to interfere with my updateColors()
and langUpdate()
functions which show the HTML correctly. So the main problem is that I am not able to send anything through mainMenuUpdate
channel and get anything but two errors as mentioned above while showing myPage.html
inside an iframe
. So I still get the error on both occations, while two times when console.log()
does not work and one time when using a button instead of an iframe
which gives one error of such and the console.log()
with args for both updateColor()
and langUpdate()
functions.
Upvotes: 2
Views: 807
Reputation: 33
As @midnight-coding mentioned about ipcRender.postMessage(channel, message, [transfer]);
as an alternative to IPC which cannot be used to send data parent --> iframe
; I decided to go with what I found from Mozilla webDocs and this 3 min YT video.
mainMenu.js:
(renderer)
// iframe \/
const mainWindow = document.querySelector('.main-window');
mainWindow.contentWindow.postMessage({
channel: 'mainMenuUpdate',
currentSkin: windowSkin,
currentLanguage,
}, '*')
Because I send it directly through renderers I avoid extra code inside main.js
, so it sends through to myPage.js
(renderer) and receives it:
window.addEventListener('message', (message) => {
if(message.data.channel == 'mainMenuUpdate') {
// I now have args over to `iframe`
console.log(message.data)
//... updateColors(...) langUpdater(...)
}
});
I still don't know about myLibrary
button, but it is not caused by the iframe
problem.
Upvotes: 1