I've been trying to get my toolbar component to emit data to another component (dat.gui -> three.js). What I assumed would be needed is creating an output emitter and that is working, but it is not working somehow. There is no actual html code inside these components.
All I need to do is emit the event with the interface holding data (currently just a boolean
, but will be expanded later). My project is also on github, if that would be clearer. I ve been reading up on a variety of ways to work with Angular, but am still pretty new. In that regard, if I made a dumb mistake please tell me because I have no idea what I am doing wrong here.
https://github.com/GrimZero/ConfiguratorAngular
settngs.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SettingsService {
$dataChange: Subject<any> = new Subject<any>();
}
toolbar.component.ts
import { GUI } from './../../../node_modules/three/examples/jsm/libs/dat.gui.module';
import { Settings } from '../settings';
import { SettingsService } from '../settings.service';
@Component({
selector: 'app-toolbar',
templateUrl: './toolbar.component.html',
styleUrls: ['../app.component.css']
})
export class ToolbarComponent implements OnInit {
settingsData: Settings;
constructor(private service: SettingsService) {
this.settingsData = this.defineSettings({ TimeNight: false });
}
defineSettings(config: Settings) {
const settings = { TimeNight: true };
if (config.TimeNight) {
settings.TimeNight = config.TimeNight;
}
return settings;
}
onChange() {
this.service.$dataChange.next(this.settingsData);
console.log('emitted');
}
ngOnInit() {
const gui = new GUI();
gui.add(this.settingsData, 'TimeNight').onChange(() => {
this.onChange();
});
}
}
threejs.component.ts
import { Component, OnInit } from '@angular/core';
import { Material } from '../material.js';
import { TimeOfDay } from '../time-of-day.js';
import { Threejscontroller } from '../threejscontroller.js';
import { SettingsService } from '../settings.service.js';
@Component({
selector: 'app-threejs',
templateUrl: './threejs.component.html',
styleUrls: ['../app.component.css']
})
export class ThreejsComponent implements OnInit {
threejs: Threejscontroller;
constructor(private service: SettingsService) { }
updateWebGL = (settingsData: any) => {
console.log('recieved message');
if (!settingsData.TimeNight) {
new TimeOfDay().SetTimeDay(this.threejs.scene);
} else {
new TimeOfDay().SetTimeDusk(this.threejs.scene);
}
}
ngOnInit() {
this.service.$dataChange.subscribe((value: any) => {
console.log(value);
// this.updateWebGL(value);
});
this.threejs = new Threejscontroller();
this.threejs.update();
}
}
You could only use @Output
to pass data from child component to parent component. I think here your approach is wrong
So you have to achieve it by using a service:
Defined a Service like bellow
@Injectable()
export class MyService {
$dataChange: Subject<any> = new Subject<any>();
}
Make sure to add it to your app.module.ts
@NgModule({
providers: [
MyService
]
})
And inject it to ThreejsComponent
and use it like bellow
export class ThreejsComponent implements OnInit {
threejs: Threejscontroller;
constructor(private myService: MyService) { }
UpdateWebGL = (settingsData: Settings) => {
console.log('recieved message');
if (!settingsData.TimeNight) {
new TimeOfDay().SetTimeDay(this.threejs.scene);
} else {
new TimeOfDay().SetTimeDusk(this.threejs.scene);
}
}
ngOnInit() {
this.threejs = new Threejscontroller();
this.threejs.update();
this.myService.$dataChange.subscribe((value: any) => {
this.UpdateWebGL(value);
});
}
}
In ToolbarComponent
use like bellow:
export class ToolbarComponent implements OnInit {
settingsData: Settings;
@Output() event: EventEmitter<Settings> = new EventEmitter<Settings>();
constructor(private myService: MyService) {
this.settingsData = this.defineSettings({ TimeNight: false });
}
defineSettings(config: Settings) {
const settings = { TimeNight: true };
if (config.TimeNight) {
settings.TimeNight = config.TimeNight;
}
return settings;
}
onChange() {
this.myService.$dataChange.next(this.settingsData);
console.log("emitted");
}
ngOnInit() {
const gui = new GUI();
gui.add(this.settingsData, 'TimeNight').onChange(() => {
this.onChange();
});
}
}
I checked your git code, the issue with your imports please change the import of ThreejsComponent
import { SettingsService } from '../settings.service.js';
to
import { SettingsService } from '../settings.service';
Hope this will help you!