I am building an electron app with angular 2 in the renderer process. My main process talks to a socket server. Whenever the user is connected to this server or disconnected, I wish to show the user's status in the view.
For this, I use electron's ipc to send a message from the main to the renderer process, like this
socket.on('connect', function() {
mainWindow.webContents.send('socket-connection-status', true);
});
socket.on('disconnect', function() {
mainWindow.webContents.send('socket-connection-status', false);
});
In my view, I then have a (simplified) angular component, like this
const ipc = require('electron').ipcRenderer;
@Component({
selector: 'status-bar',
template: '{{status}}'
})
export class StatusBarComponent {
private status: string = "offline";
constructor() {
ipc.on('socket-connection-status', function(event, status) {
if (status===true) {
this.status = 'online';
} else {
this.status = 'offline';
}
console.log(status); // Successfully logs true|false
console.log(this.status); // Successfully logs online|offline
})
}
}
I successfully log the messages from main process.
The problem is that angular 2 does not 'know' electron's ipc, so change detection is not triggered for status
. I have seen several people struggling with this issue, but haven't come across a 'true' solution.
I have tried to solve it with injecting ApplicationRef
, ChangeDetectorRef
and ngZone
(ref: Triggering Angular2 change detection manually), but none of the methods provided (tick()
, detectChanges()
, run()
respectively) happened to provide a solution.
Apparently, 'within' ipc.on
I cannot reference my class' properties/methods/injectables as I run into errors: For instance, this (https://github.com/JGantner/angular2_change_detection_issue/blob/master/browser/security-level-indicator-component.ts) solution (which I find not very elegant) results in Uncaught TypeError: Cannot read property 'markForCheck' of undefined
.
Could somebody please help me out with how to make change detection work in my case?
One way I have found in which I at least get the functionality that I need/want:
status-bar.component.ts
:
const ipc = require('electron').ipcRenderer;
import { SocketStatusService } from '../services/socket-status.service';
@Component({
selector: 'status-bar',
template: '{{status}}'
})
export class StatusBarComponent {
private status: string = "offline";
status$: Subscription;
constructor(private socketStatusService: SocketStatusService, private ref: ApplicationRef) {
ipc.on('socket-connection-status', function(evt, status) {
if (status===true) {
this.service.updateSocketStatus('online');
} else {
this.service.updateSocketStatus('offline');
}
}.bind({service: socketStatusService}))
this.status$ = this.socketStatusService.socket_status$.subscribe(
status => {
this.status = status;
this.ref.tick();
}
)
}
socket-status.service.ts
:
@Injectable()
export class SocketStatusService {
private socket_status = new BehaviorSubject<string>("offline");
socket_status$ = this.socket_status.asObservable();
updateSocketStatus(status: string) {
this.socket_status.next(status);
}
}
Although this works, I have the feeling there must be a more elegant way to achieve this behavior.
Best case scenario though would be a means to set the component's class properties directly in the ipc callback and trigger change detection... So far I have not been able to get that to work, so any help would be appreciated.
(p.s. Also, I am not sure why I have to manually trigger this.ref.tick()
, which is not something I remember having had to do to trigger change detection from streams in earlier beta versions of angular 2...)
this.status
is set on wrong object, and markForCheck
doesn't work because of this too. Event handler should be an arrow in order for proper context to be provided.
With proper this
context any known way to trigger change detection should work.
For example
ipc.on('...', (evt, status) => {
...
this.changeDetectorRef.detectChanges();
});
Or
ipc.on('...', (evt, status) => {
setTimeout(() => {
...
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With