角度6:将孩子的点击事件发送给父母

时间:2018-10-16 12:49:35

标签: angular events nested click parent-child

编辑: 它仍然不起作用,也不会引发任何错误。 我编辑了代码,并从parent.component.ts

添加了部分代码

我有一个侧面导航栏的父组件和子组件,它们嵌套在父组件的主体中并包含iframe。 我希望在iframe上发生点击事件时,我将返回发生事件的父项,以便我可以将该视频标记为在父项的侧边栏中观看的带有“ V”的视频。

父component.ts

// ..... 

export class CoursePlayComponent implements OnInit {
    course: ICourse;
    courseId: number;

    // current user
    public currentUser: IUser;

    // variables for current lesson
    public current: IVideo;
      
    constructor(private courseService: CourseService,
     private route: ActivatedRoute,
     private router: Router,
     private userService: UserService) {
         this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
      }
       
    ngOnInit() {
     // save this course id from course-detail and get http request from the service
     this.courseId = JSON.parse(localStorage.getItem("courseId"));
     this.getCourse(this.courseId);
    }
    
    // get course by id from service
    getCourse(id:number) {...}
    
    // get current lesson by unit and lesson position in course
    getCurrent(unit_position: number, lesson_position: number) { ... }
    
    // check if the lesson already watched
    isLessonIncluded(course_id: number, lesson_id: number) {
      return this.userService.isLessonIncluded(course_id, lesson_id);
    }
  
    // check the value from child lesson and add the new lesson to the completed lessons array
    watched(state) {
      console.log("parent-video watched: ", state);
      
      // update user data array
      this.userService.addToCompletedLessons(this.course.id, this.current.id);
    }   
 }

parent.component.html:

<mat-sidenav-container fullscreen *ngIf="course">
  <mat-sidenav #sidenav mode="side" class="app-sidenav">
    <mat-toolbar id="sidenav" color="primary">
      <button mat-icon-button (click)="sidenav.toggle()" class="mat-icon-button sidenav-toggle-button" [hidden]="!sidenav.opened">
        <mat-icon aria-label="Menu" class="material-icons">close</mat-icon>
      </button>
    </mat-toolbar>
      <mat-nav-list *ngFor="let unit of course.units">
        <h6 class="course-list-title">Unit {{ unit?.position }}: {{ unit?.name }}</h6>
        <a mat-list-item *ngFor="let lesson of unit.videos" class="sidenav-link course-item" [routerLink]="['/courses' , course?.id , 'unit' , unit?.position , 'lesson' , lesson?.position]" (click)="sidenav.toggle()" (click)="getCurrent(unit?.position,lesson?.position)">
          <span mat-line class="title">Lesson {{lesson?.id}}: {{lesson?.name}}</span>
          <span *ngIf="isLessonIncluded(course.id, lesson.id)" class="fas fa-check" style="color:lightgreen;"></span>
        </a>
    </mat-nav-list>
  </mat-sidenav>

<!-- ... -->

    <div class="course-body container-fluid text-center">
      <course-lesson *ngIf="showLesson == true" (clicked)="watched($event)" [lessonId]="current?.id" [lessonName]="current?.name" [lessonData]="current?.data" [totalLesoons]="totalLesoons"></course-lesson>
   
    </div>
</mat-sidenav-container>

child.component.ts:

// ....

export class CourseLessonComponent implements OnInit {
  @Input() lessonId: number;
  @Input() lessonName: string;
  @Input() lessonData: string;
  @Input() totalLesoons: number;
  
  @Output() clicked = new EventEmitter();

  clicked: boolean = false;

  constructor(private courseService: CourseService,
      private route: ActivatedRoute,
      private router: Router) { }

  ngOnInit() { }
  
    watchedVideo() {
    console.log("child- video watched");
      this.clicked.emit(true);
  }
}

child.component.html:

<h1 class="lesson-title">{{lessonName}}</h1>
  <p class="small-text" *ngIf="totalLesoons > 0">lesson {{lessonId}} of {{totalLesoons}}</p>
  <hr>
  <iframe (click)="clicked = true" frameborder="0" allowfullscreen="true" [src]='lessonData | safe'></iframe>

1 个答案:

答案 0 :(得分:3)

您可以利用@Output@EventEmitter通过子组件通知您的父组件。

子组件ts

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ActivatedRoute, Router, Routes, NavigationEnd } from '@angular/router';
import { DomSanitizer } from '@angular/platform-browser';

import { CourseService } from '../../course.service';

@Component({
  selector: 'course-lesson',
  templateUrl: './course-lesson.component.html',
  styleUrls: ['./course-lesson.component.sass']
})
export class CourseLessonComponent implements OnInit {

  @Input() lessonId: number;
  @Input() lessonName: string;
  @Input() lessonData: string;
  @Input() totalLesoons: number;
  @Output() paused = new EventEmitter<string>();

  pauseClick(){
    this.paused.emit(true);
  }

  constructor(private courseService: CourseService,
      private route: ActivatedRoute,
      private router: Router) { }

  ngOnInit() { }

}

子组件html

<iframe (click)="pauseClick()" frameborder="0" allowfullscreen="true" [src]='lessonData | safe'></iframe>

父组件HTML

<course-lesson (paused)="onPausedClick($event)" *ngIf="showLesson == true" [lessonId]="current?.id" [lessonName]="current?.name" [lessonData]="current?.data" [totalLesoons]="totalLesoons"></course-lesson>

父项ts

public pauseState = false;
onPausedClick(state){
   console.log("Paused is clicked ", state);
   this.pauseState = state;
}