0

I have an app with a menu and a router-outlet where the different components are displayed. All those components have forms with a saveForm function. I would like to know how I can call the saveForm function from the current component when I click an item of the menu. Also how to stop propagation (or prevent default) if the form hasn't been saved.

app.component.html:

...
<app-navbar></app-navbar>
<router-outlet></router-outlet>
...

component1.component.ts:

...
saveForm() {

}

componentN.component.ts:

...
saveForm() {

}
igogra
  • 415
  • 1
  • 5
  • 18
  • You could create a shared service and all the components that have that function will be subscribed to it. Each time you click one option you trigger an Observable from the shared service passing a parameter (the name of the component or whatever). And the rest of components would be subscribed to it. As soon as they receive the parameter that matches their component, they trigger the function... This is the Shared Service: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service – SrAxi Nov 14 '17 at 15:48

1 Answers1

1

I solved it. I created a shared service:

@Injectable()
export class MenuFormService {
    private menuFormAnounceClickSubject = new Subject();
    private menuFormConfirmationSavedSubject = new Subject<boolean>();

    menuFormAnounceClick$ = this.menuFormAnounceClickSubject.asObservable();
    menuFormConfirmationSaved$ = this.menuFormConfirmationSavedSubject.asObservable();

    anounceClickMenuForm() {
        this.menuFormAnounceClickSubject.next();
    }

    confirmSaveMenuForm(saved: boolean) {
        this.menuFormConfirmationSavedSubject.next(saved);
    }
}

In the menu component:

export class MenuComponent implements OnInit {
    currentRouteItemMenu: string;

    constructor(
        private menuFormService: MenuFormService,
        private router: Router
    ) {}

    ngOnInit(): void {
        this.menuFormService.menuFormConfirmationSaved$.subscribe(
            saved => {
                if (saved) {
                    this.router.navigate([this.rutaItemActual]);
                }
            });
    }

    onClick(currentRouteItemMenu: string): void {
        this.currentRouteItemMenu = currentRouteItemMenu;
        this.menuFormService.anounceClickMenuForm();
    }
}

In every component with forms:

export class NComponent implements OnInit, OnDestroy {
    subscription: Subscription;

    constructor(
        private menuFormService: MenuFormService
    ) {}

    ngOnInit(): void {
        this.subscription = this.menuFormService.menuFormAnounceClick$.subscribe(
            response => {
                if (this.form.valid) {
                    this.menuFormService.confirmSaveMenuForm(true);
                } else {
                    this.menuFormService.confirmSaveMenuForm(false);
                }
        });

    ngOnDestroy(): void {
        this.subscription.unsubscribe();
    }
}
igogra
  • 415
  • 1
  • 5
  • 18
  • this looks like it works for all kinds of dataflow scenarios, I rigged up an almost app global shared data object through this basic injectable service pattern. not sure if that is a recommended pattern to use, but it worked for a start! – stackuser83 Sep 26 '18 at 00:34