Structure of the app:
AppService AppComponent -> HeroComponent -> WeaponComponent -> ButtonComponent
When someone clicks on the button (ButtonComponent), I would like to open a modal dialog in the AppComponent.
The best way I can think of is making a dialogObservable in the AppService. The ButtonComponent sets the observable and the AppComponent listens to it, and shows the dialog when there is a dialog set.
This already feels a bit messy.
But to make it worse, I also need buttons in the Dialog. When someone clicks on the "OK" button, I want to call an action from the WeaponComponent. Which is impossible, as far as I know. So what do I do? Create another observable in the service, and listen to it in the WeaponComponent.
This feels very messy, and I feel there must be a better way. I just can't figure it out.
I had a similar problem and I solved it by adding a modal in my root module component, and providing a ModalService
accross my app.
ModalService
is used as an event dispatcher, to dispatch the modal event.
Exemple with just signatures (to be easy to understand, implementation is not that hard):
@Injectable()
export class ModalService{
public registerModal(name:string, onPop:()=>void):void;
public popModal(name:string):void;
}
This way your ModalComponent
can be anywhere (and you can have a lot of modals with different names) and you can pop it from anywhere since you just need to get the ModalService
.
Note that to make this work, you have to use only one instance of ModalService
, so it has to be declared in your module.forRoot()
method.
EDIT:
To fix the context issue, you can declare your function and store it in a variable, this way:
function foo():any{
}
becomes
foo=():any => {
}
then you can pass the callback method to your modal using this.foo
, it will not loose the context.