Search code examples
javascriptangularrxjsrxjs-observables

Nested Child UI component is not working on keypress event in Parent component in Angular


I am trying to add shortcut to open nested child UI Tab component through keyboard keypress event. But, to load Child nested Tab component, first parent should be loaded. Below is UI tree:

  • |--Parent Component
  • |----Child Component -- It contains 4 tabs.
  • |------Child Tab Component -- First Tab.

Keypress event is written inside Parent Component,

@HostListener('window:keyup', ['$event'])
keyEvent(event: KeyboardEvent) {
    if(event.code === "KeyR") {
        //here storing event details in service
        MyService.store({
            key: HANDLE_KEY_EVENT,
            data: event
        })
    }
}

And in Child component, Child nested Tab should get open on the basis of subscribing the stored event details. Below is code snippet:

private readonly subscriber: Subscription[] = [];

    ngOnInit(): void {
        this.subscriber.push(
            MyService.observe(HANDLE_KEY_EVENT).subscribe((event)=>{
                if(event.code === "KeyR"){
                    openTab()
                }
            })
        )
    } 

But openTab() function is not calling with above code snippet i.e. written inside subscribe. In below code snippet openTab() function is calling, if it written directly inside ngOnInit() i.e. without subscribe:

ngOnInit(): void {
    openTab()
}

My requirement is to write openTab() function issue inside subscribe.

So, please help me in fixing above issue.

Below is the implementation of store and observe function inside MyService.

private subject:Subject<any> = new Subject();

public store(key:string,data:any){
    const event = {
        name: key,
        data: data
    };
    this.subject.next(event);
}

public observe(key:string):Observable<any>{
    return new Observable<any>((observer)=>{
        this.subject.subscribe(res=>{
            if(res.name === key){
                observer.next(res.data);
            }
        })
    });
}

Solution

  • There's some errors in your code

    First, you need inject in constructor the service, both in child and parent

      constructor(private MyService:MyService){}
    

    Your function store should destructure the arguments, else give you error "expect 2 arguments but only 1 is give". See the destructure is in the way {variable1,variable2,...}:{variable1:typeOfVariable1,variable2:typeOfVariable2,...}

    public store({key,data}:{key:string,data:any}){
        const event = {
            name: key,
            data: data
        };
        this.subject.next(event);
    }
    

    You need use "this" in service: this.MyService.

    NOTE: I leave your name, but generally we use the variable in lower case: constructor(private myService:MyService){}

    I made a little stackblitz I hope help you