1

I am working on a large Angular 2 app separated in different modules, like so:

  • app.module:
    • user.module
    • supplier.module
    • shared.module
    • etc.

From my shared module, I am calling a Bootstrap 4 modal component for all my modals in the app, that I customize through a modal configuration object using the @Input decorator. Here's what my modal component .ts looks like:

modal.component.ts:

export class ModalComponent {

    constructor() { }

    public modalMethods = new ModalActionMethods();

    @Input() modalConf: ModalModel;

}

Then from inside the modal template, I am referencing the modalConf object, like so:

modal.template.html:

<div class="bg-modal-container" [hidden]="!modalConf.isOpen">

Finally, I pass the data to the modal component when I use it in the view of whatever component needs it:

whatever.component.html:

<modal [modalConf]="modalOptions"></modal>

modalOptions is referencing an object defined inside my whatever.component's main class.

whatever.component.ts

export class WhatevertComponent {
    private modalOptions = {
        isOpen: false,
        title: "Some Modal Title"
        // etc.
    }
}

So far so good.

Now, for my users module, since I know I will be using my modal component a lot across multiple components, I would like to do things a little differently, since this module serves different components depending on the route:

users.routing.ts:

const routes: Routes = [
    {
        path: '', component: UsersComponent,
        children: [
            { path: 'creation', component: UserCreationComponent },
            { path: 'management', component: UserManagementComponent }
        ]
    }
];

The question:

What I would like to do is insert my modal component inside my main UsersComponent (placing the modalOptions object inside it's main class and the modal selector in the view, same as above for whatever-component), but also be able to somehow modify the modal configuration from within other child components, such as creation, management, etc., so that I can show relevant child component data in my modal. What I'm trying to avoid is to insert (and create a separate modalConf object for) my modal component inside every child component that will be using/manipulating it.

What would be the best approach to do this? I am open to suggestions.

3
  • What i am interpreting from the question is that you are trying to achieve cross component communication, for this you can use service class as a intermediate to pass data using event emitter Commented Jan 16, 2017 at 19:49
  • If I'm not mistaken, this sounds like a perfect use case for an Rxjs store. github.com/ngrx/store Commented Jan 16, 2017 at 20:40
  • Hello, Rahul Singh. Thanks for your feedback. I'm already using a service as part of my modal component with a unique getDefaultConf() method defined. Do you think that extending this service with two new setter and getter methods for the currentConf and binding my @Input decorator to the getter would do the trick? Commented Jan 16, 2017 at 20:42

1 Answer 1

1

So... Following Jaime and Rahul's comments to my original question, I found a potential solution to my problem. As recommended by them, I used RxJS Observables in a service to allow child components of whatever-component to interact and communicate. I'll post my implementation below, hoping this might help others with the same issue.

First, I expanded my modal service with two new methods for setting and getting the modal configuration.

modal.service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import { ModalModel } from '../../models/modal.model';

@Injectable()
export class ModalService {

    private currentConf: ModalModel;

    private confSubject: Subject<ModalModel> = new Subject<ModalModel>();

    public getDefaultConf() {
        return {
            // some default conf
        };
    }

    public setCurrentConf(conf: ModalModel): void {
        this.currentConf = conf;
        this.confSubject.next(conf);
    }

    public getCurrentConf(): Observable<ModalModel> {
        return this.confSubject.asObservable();
    }

}

Then I moved the modal component call from my child component into my main component (whatever-component). Inside this component, I imported the modal service, initialized the modal with default config and subscribed to the service's get method on ngInit.

whatever.component.ts

import { ModalService } from '../../shared/modal/modal.service';
// ...

export class WhateverComponent {

    public modalOptions: any = this._modalService.getDefaultConf();

    ngOnInit() {
        this._modalService.getCurrentConf().subscribe( (conf: any) => {
            this.modalOptions = conf;
        });
    }
}

Finally, from inside child components, I imported the modal service and used its set method whenever I needed to update the modal config:

this._modalService.setCurrentConf(childCompModalConfig);

What I'm not sure of is if I need to unsubscribe from the service on ngDestroy or if RxJS takes care of this automatically.

If someone has a better approach and wishes to share it, please don't hesitate. Thanks!

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.