Electron and angular ipcrender - javascript

I try to call some electron api from angular and respone on it. For test i try to hide block:
electron.ts:
import {app,BrowserWindow,BrowserWindowConstructorOptions, ipcMain} from 'electron'
let window:any = null
app.whenReady().then(()=>{
const options:BrowserWindowConstructorOptions = {
width:300,
height:600,
title:"test",
show:false,
webPreferences: {
nodeIntegration: true,
contextIsolation : false
}
}
window = new BrowserWindow(options)
window.loadFile('some path')
window.webContents.on('did-finish-load',()=>{
window.show()
ipcMain.on('test',(value)=>{
window.webContents.send('test2')
})
})
})
app-component.html:
<div *ngIf='__flag'><h1>Test</h1>
<button (click)='clickFunction()'>Test button</button>
</div>
app-component.ts:
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { ElectronService, NgxElectronModule } from 'ngx-electron';
#Component({
selector: 'app-component',
templateUrl: './app-component.html',
})
export class AppComponentComponent implements OnInit {
__flag:boolean = true
constructor(private route:Router, private elect:ElectronService) { }
ngOnInit(): void {
}
clickFunction(){
this.elect.ipcRenderer.send('test')
this.elect.ipcRenderer.on('test2',()=>{
this.__flag=false
console.log(this.__flag);
})
}
}
But div removes only if i clicked twice on button. Why it happens? And how can i fix that? I need to hide block then button clicked

You are only setting up the event listener(this.elect.ipcRenderer.on('test2') in your clickFunction after you've sent the message to the main process. Therefore the listener isn't listening yet when the call from the main process arrives. It works on the second click because the listener has been configured in the first click and therefore you get the message.
Move your event listener to the ngOnInit function and it should be fine.
ngOnInit(): void {
this.elect.ipcRenderer.on('test2',()=>{
this.__flag=false
console.log(this.__flag);
});
}
clickFunction(){
this.elect.ipcRenderer.send('test');
}

Related

How to refresh the page after routing to that page on click of a button from previous page

I have 2 pages, one home and page2. when I click a button on home page it is routing to page2. Now after clicking the button on home,when I comes to page2 it should be refresh,since there is some cache issue in my project. I added the window.location.reload() on ngoninit,but here my page is continuously refreshing.
Here is the code below.
home.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-home',
template: '<button (click)="gonextPage()">Go to next page</button>',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
imageSource :any;
statusdata1: any;
moreThanTen:boolean = false;
showit:boolean = false;
groupList:any = [];
constructor(private router: Router) { }
gonextPage(){
this.router.navigateByUrl('/page2');
}
ngOnInit() {
// window.location.reload();
/* First data */
let response =
{"vehicle_number":1,"vehicle_name":"car","status":"yellow"}
let response1 = {"vehicle_number":0,"vehicle_name":"car","status":"yellow"}
let response2 = {"vehicle_number":2,"vehicle_name":"car","status":"yellow"}
this.groupList.push(response,response1,response2);
console.log(this.groupList);
}
}
page2.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-page2',
template: '',
styleUrls: ['./page2.component.css']
})
export class page2Component implements OnInit {
imageSource :any;
statusdata1: any;
moreThanTen:boolean = false;
showit:boolean = false;
groupList:any = [];
constructor(private router: Router) { }
ngOnInit() {
window.location.reload();
/* First data */
let response =
{"vehicle_number":1,"vehicle_name":"car","status":"yellow"}
let response1 = {"vehicle_number":0,"vehicle_name":"car","status":"yellow"}
let response2 = {"vehicle_number":2,"vehicle_name":"car","status":"yellow"}
this.groupList.push(response,response1,response2);
console.log(this.groupList);
}
}
I remove the previous edited answer because it is bullied.
The only way is to use an information that persists even when reloading the js (on window.location.reload();), because all the rest of the information would be lost. You can use the localStorage (with localStorage.setItem('firstReload', 'true'); ).
ngOnInit() {
if (!localStorage.getItem('firstReload') || localStorage.getItem('firstReload') == 'true') {
localStorage.setItem('firstReload', 'false');
window.location.reload();
} else {
localStorage.setItem('firstReload', 'true');
}
}
Here a working modified example: https://stackblitz.com/edit/angular-correct-routing?file=src%2Fapp%2Fpage.component.ts
You dont need to manually reload. If you route to a specific component always you will get a new component. If you can explain more about ur problem I can help you.

Trigger click event of an ionic3 element programatically with jquery

I am trying to trigger the (ionic) click event of an element manually, from jquery or native dom events.
Let's say for example I have the following:
entry.html
<button [id]="id" (click)="entryClicked()></button>
entry.ts
#Component({
selector: 'entry',
templateUrl: 'entry.html',
})
export class EntryComponent {
constructor() {}
id = "entry_1"
entryClicked () {
console.log(id +" has been clicked")
}
}
From another service, I would like to trigger the click event on entry_1.
Problem: this other service is completely separate from the first, it's a provider and to my knowledge, I cannot use #ViewChild and #ViewChildren from it. So I cannot directly access functions of the entry component.
externalService.ts
import { Injectable } from '#angular/core';
import * as $ from 'jquery';
#Injectable()
export class ExternalServiceProvider {
constructor( ) { }
someEvent () {
$("#entry_1").click();
}
}
Triggering someEvent() doesn't trigger entryClicked() like I hope it would.
It's not a problem of loading, the #entry_1 element is found by jquery. It's just that the (click) event bound to the element by ionic doesn't seem to be related to the jquery click event.
Same problem if I use $("#entry_1")[0].click().
However, if I click the element in the page, it fires properly.
How can I fire the original ionic click event from the DOM, with or without jquery?
I think you can use Ionic Events to achieve this as described here.
Events is a publish-subscribe style event system for sending and
responding to application-level events across your app.
Modify your code like this:
externalService.ts
import { Injectable } from '#angular/core';
import * as $ from 'jquery';
import { Events } from 'ionic-angular';
#Injectable()
export class ExternalServiceProvider {
constructor(public events: Events) { }
someEvent () {
this.events.publish('triggerClickEvent', "triggerClickEvent");
}
}
entry.ts
import { Events } from 'ionic-angular';
#Component({
selector: 'entry',
templateUrl: 'entry.html',
})
export class EntryComponent {
constructor(public events: Events) {
events.subscribe('triggerClickEvent', (data) => {
console.log('Event triggered' , data);
this.entryClicked();
});
}
id = "entry_1"
entryClicked () {
console.log(id +" has been clicked")
}
}

Interdependent component which need to communicate each other

I am in a situation like i have 5 interdependent component which need to communicate each other. For example if i click on a button A on all other 4 component need to listen to the click and alert something. The same way button in other component also listened by all other 4. Need a best solution on how to achieve this.
here is my code snippet
import { Component, OnInit } from '#angular/core';
import { CommonService } from 'broadcast-recive/service/common-service';
#Component({
selector: 'app-broadcaster',
templateUrl: './broadcaster.component.html',
styleUrls: ['./broadcaster.component.css']
})
export class BroadcasterComponent implements OnInit {
constructor(private commonservice: CommonService) { }
ngOnInit() {
}
broadCastMe(): void
{
this.commonservice.btnClickedInBroadCasterComponent((<HTMLButtonElement>event.target).id);
}
}
import { Component, OnInit } from '#angular/core';
import { CommonService } from 'broadcast-recive/service/common-service';
#Component({
selector: 'app-listener1',
templateUrl: './listener1.component.html',
styleUrls: ['./listener1.component.css']
})
export class Listener1Component implements OnInit {
constructor(private commonservice: CommonService) { }
ngOnInit() {
this.commonservice.clickStatusForBroadCastercomponentBtn.subscribe((id: string) => {
alert('alert from listner 1');
})
}
}
import { Component, OnInit } from '#angular/core';
import { CommonService } from 'broadcast-recive/service/common-service';
#Component({
selector: 'app-listener2',
templateUrl: './listener2.component.html',
styleUrls: ['./listener2.component.css']
})
export class Listener2Component implements OnInit {
constructor(private commonservice: CommonService) { }
ngOnInit() {
this.commonservice.clickStatusForBroadCastercomponentBtn.subscribe((id: string) => {
alert('from listner 2');
});
}
}
Here am always getting alert box "from listener 2 " , My requirement is its should trigger both the listener. Please help me refactoring the code. blow is my service where am using rx js for subscribing.
import {Subject} from 'rxjs/Subject';
import { Injectable } from '#angular/core';
#Injectable()
export class CommonService {
public clickStatusForBroadCastercomponentBtn = new Subject<string>();
public clickStatusForBcomponentBtn = new Subject<string>();
btnClickedInBroadCasterComponent(btnId: string): void {
this.clickStatusForBroadCastercomponentBtn.next(btnId);
}
btnClickedInComponentB(btnId: string): void {
this.clickStatusForBcomponentBtn.next(btnId);
}
}
You can do this using rxjs Subject declared in a service. Lets say, you have a service named AService:
import {BehaviorSubject} from 'rxjs/BehaviorSubject;
#Injectable()
export class AService {
public clickStatusForAcomponentBtn = new BehaviorSubject<string>('');
public clickStatusForBcomponentBtn = new BehaviorSubject<string>('');
btnClickedInComponentA(btnId: string): void {
this.clickStatusForAcomponentBtn.next(btnId);
}
btnClickedInComponentB(btnId: string): void {
this.clickStatusForAcomponentBtn.next(btnId);
}
}
Now, you can use this service in all your components those need to communicate with each other like this:
export class AComponent implement OnInit {
constructor(private aService: AService){}
ngOnInit(){
this.aService.clickStatusForBcomponentBtn .subscribe((clickedBtnId:string)=> {
// whenever button with id clickedBtnId clicked in Component B this observer
// will be get executed.So, do your necessary operation here.
}
}
btnClickListenerForA(event:Event){ /* in this component template you'll bind this listener with your button click event */
this.aService.btnClickedInComponentA((<HTMLButtonElement>event.target).id);
}
}
export class BComponent implement OnInit {
constructor(private aService: AService){}
ngOnInit(){
this.aService.clickStatusForAcomponentBtn .subscribe((clickedBtnId:string)=> {
// whenever button with id clickedBtnId clicked in Component A this observer
// will be get executed.So, do your necessary operation here.
}
}
btnClickListenerForB(event:Event){ /* in this component template you'll bind this listener with your button click event */
this.aService.btnClickedInComponentB((<HTMLButtonElement>event.target).id);
}
}
If you review the code, you'll understand two subjects are used to pass communication between two component. This way, you'll able to communicate between any number of components.
Thus, you can declare a rxjs subject for every button and for listening any button's click event you've to subscribe that buttons subject in other components where you want to listen that buttons event.
Hope this will guide you in a right direction.
You should use a shared service with a BehaviorSubject to emit any changes to any component listing to it please take a look at my answer Here I posted it like a few seconds ago on a similar question.

How to trigger change() in a angular form by a custom control without an input

I do want to create a custom control which does not include any input. Whenever the control changes, I do want to save the complete form.
Our current approach uses the form-changed-event like this:
<form #demoForm="ngForm" (change)="onChange()">
<custom-input name="someValue" [(ngModel)]="dataModel">
</custom-input>
</form>
As you can see, we use the "change"-event to react to any change in the form.
This works fine as long as we have inputs, checkboxes, ... as controls.
But our custom control does only exist out of a simple div we can click on. Whenever I click on the div the value of the control is increased by 1. But the "change"-event of the form is not fired. Do I somehow have to link my custom control to the form? Or are there any events which need to be fired?
import { Component, forwardRef } from '#angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '#angular/forms';
#Component({
selector: 'custom-input',
template: `<div (click)="update()">Click</div>`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
}]
})
export class CustomInputComponent implements ControlValueAccessor {
private onTouchedCallback: () => void = () => {};
private onChangeCallback: (_: any) => void = () => {};
update(){
this.value++;
}
get value(): any {
return this.innerValue;
};
set value(v: any) {
console.log("Change to");
if (v !== this.innerValue) {
this.innerValue = v;
this.onChangeCallback(v);
}
}
writeValue(value: any) {
if (value !== this.innerValue) {
this.innerValue = value;
}
}
registerOnChange(fn: any) {
this.onChangeCallback = fn;
}
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
}
I've created a plunker to demonstrate the problem:
https://plnkr.co/edit/ushMfJfcmIlfP2U1EW6A
Whenever you click on "Click" the model-value is increased, but there is no output on the console, as the change-event is not fired... (There is a console.log linked to the change-event)
Thanks for your replies.
Finally I found the following solution to this problem:
As Claies mentioned in the comment, my custom component does not fire the change event. Therfore the form does never know about the change. This has nothing todo with angular, but as said is the expected behaviour of a input/form.
The easiest solution is to fire the change-event in the customcontrol when a change happens:
constructor(private element: ElementRef, private renderer: Renderer) {
}
public triggerChanged(){
let event = new CustomEvent('change', {bubbles: true});
this.renderer.invokeElementMethod(this.element.nativeElement, 'dispatchEvent', [event]);
}
That's it, whenever I called "onControlChange(..)" in my custom component, then I fire this event afterward.
Be aware, that you need the Custom-Event-Polyfill to support IE!
https://www.npmjs.com/package/custom-event-polyfill
You need to emit the click event of div to its parent. so that you can handle the event.
Plunker Link
Parent component:
import { Component, forwardRef, Output, EventEmitter } from '#angular/core'; // add output and eventEmitter
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '#angular/forms';
#Component({
selector: 'custom-input',
template: `<div (click)="update($event)">Click</div>`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
}]
})
export class CustomInputComponent implements ControlValueAccessor {
private onTouchedCallback: () => void = () => {};
private onChangeCallback: (_: any) => void = () => {};
#Output() clickEvent = new EventEmitter(); // add this
update(event){
this.value++;
this.clickEvent.emit(event); // emit the event on click event
}
get value(): any {
return this.innerValue;
};
}
child component:
//our root app component
import {Component} from '#angular/core'
#Component({
selector: 'demo-app',
template: `
<p><span class="boldspan">Model data:</span> {{dataModel}}</p>
<form #demoForm="ngForm">
<custom-input name="someValue"
[(ngModel)]="dataModel" (clickEvent) = onChange()> // handling emitted event here
Write in this wrapper control:
</custom-input>
</form>`
})
export class AppComponent {
dataModel: string = '';
public onChange(){
console.log("onChangeCalled");
}
}
Thanks Stefan for pointing me in the right direction.
Unfortuantely Renderer (which has invokeElementMethod()) has recently been deprecated in favor or Renderer2 (which does not have that method)
So the following worked for me
this.elementRef.nativeElement.dispatchEvent(new CustomEvent('change', { bubbles: true }));
It seems that change event is not fired on form when you call ControlValueAccessor onChange callback (callback passed in registerOnChange function), but valueChanges observable (on the whole form) is triggered.
Instead of:
...
<form (change)="onChange()">
...
you can try to use:
this.form.valueChanges
.subscribe((formValues) => {
...
});
Of course, you must get proper form reference in your component.

On router link click event - angular2

Hey I have this component (this is my parent controller):
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
templateUrl: 'user.component.html'
})
export class UserComponent implements OnInit {
isCompleted: Boolean = false;
constructor(private router: Router) {
this.router.events.subscribe((v) => {
this.isCompleted = true;
})
}
ngOnInit() {
}
}
UserComponent.isCompleted is a variable used by loading bar.
I have subscribed to router events and value of UserComponent.isCompleted will be changed when router done loading. I need to change UserComponent.isCompleted to false on router link click.
I know I can do it with click event like this:
<a class="item" [routerLink]="['/dashboard']" [routerLinkActive]="['active']" (click)="myFnc()">Dashboard</a>
But I looking for any other way to make it global.

Categories

Resources