Search code examples
angularrxjs

How can I change my component to use RxJs


I am trying to get familiar with RxJs and for the learning purpose I want to know how to change following code or is it even possible.

In my project I have component MeetingObjectComponent that also has child ChatComponent. Both of them have some animations to expand them that are triggered whenever user clicks on MeetingObjectComponent. The problem is that I need to prevent user from spam-clicking the components bcs it makes animation trigger multiple times that is forbidden. Currently in the ChatComponent template I keep track of @trigger.done event and emit on it signalizing the parent component that this element is clickable again.

Here are the components themself.

Component({
  selector: 'app-chat',
  templateUrl: './chat.component.html',
  styleUrls: ['./chat.component.css'],
  animations:[trigger('openClose', [...])]  
})
export class ChatComponent {
  @Input() isExpanded: boolean | undefined;

  @Output() animationComplete = new EventEmitter<null>();
}
@Component({
  selector: 'app-meeting-object',
  templateUrl: './meeting-object.component.html',
  styleUrls: ['./meeting-object.component.css'],
  animations: [
    trigger('highlightDim', [...])
  ]
})
export class MeetingObjectComponent {
  @Input() public meetingData: Meeting | undefined;

  public isExpanded: boolean = false;
  public isChildAnimationComplete: boolean = true;

///This method is bound to (click)
  expand(): void { 
    if (this.isChildAnimationComplete) {
      this.isExpanded = !this.isExpanded;
      this.isChildAnimationComplete = false;
    }
  }
}

Here is the snippet of MeetingObjectComponent template

<div class="meeting" (click)="expand()" [@highlightDim]="isExpanded">
  </div>
<app-chat
  [isExpanded]="isExpanded"
  (animationComplete)="isChildAnimationComplete = true"
></app-chat>

I want to know how can I implement the same mechanism using RxJs if it is possible


Solution

  • Instead of using (click)="expand()", what about using RxJs.fromEvent like below

    In your component HTML file

    <div #meeting class="meeting" [@highlightDim]="isExpanded"></div>
    

    And in your component TypeScript file

    destroy$ = new Subject()
    
    @ViewChild('meeting')
    divRef: ElementRef<HTMLDivElement>;
    
    ngAfterViewInit(): void {
      fromEvent(this.divRef.nativeElement, 'click')
        .pipe(
          throttleTime(300),
          tap(() => expand())  // or emit the output 
          takeUntil(this.destroy$),  // don't forget to unsubscribe
        )
        .subscribe();
    }
    
    ngOnDestroy() {
      this.destroy$.next()
      this.destroy$.complete()
    }