在父组件中获取子组件引用

时间:2018-12-19 10:16:34

标签: components angular6 parent-child

我是Angular的新手,并且遇到了问题。任何人都可以帮助我弄清楚我在父组件中做错了什么。我无法在父项中获得子项引用。我已经遵循以下参考,但没有成功。

Angular 2 @ViewChild annotation returns undefined https://expertcodeblog.wordpress.com/2018/01/12/angular-resolve-error-viewchild-annotation-returns-undefined/

父母:

import { Component, OnInit, OnDestroy, ViewChild, HostListener, AfterViewInit, ViewChildren, QueryList } from '@angular/core';
import { Router, NavigationEnd, NavigationStart } from '@angular/router';
import { NavItem, NavItemType } from '../../md/md.module';
import { Subscription } from 'rxjs/Subscription';
import { Location, LocationStrategy, PathLocationStrategy, PopStateEvent } from '@angular/common';
import 'rxjs/add/operator/filter';
import { NavbarComponent } from '../../shared/navbar/navbar.component';
import PerfectScrollbar from 'perfect-scrollbar';
import { ChatService } from 'app/services/chat.service';
import swal from 'sweetalert2';
import { JitsiService } from 'app/services/jitsi.service';
import { UserService } from 'app/services/user.service';
import { ConferenceStudentComponent } from 'app/conference-student/conference-student.component';

declare const $: any;

@Component({
  selector: 'app-layout',
  templateUrl: './admin-layout.component.html'
})

export class AdminLayoutComponent implements OnInit, AfterViewInit {
    public navItems: NavItem[];
    private _router: Subscription;
    private lastPoppedUrl: string;
    private yScrollStack: number[] = [];
    url: string;
    location: Location;

    @ViewChild('sidebar') sidebar: any;
    @ViewChild(NavbarComponent) navbar: NavbarComponent;
    @ViewChildren(ConferenceStudentComponent) stuConf: QueryList<ConferenceStudentComponent>;
    constructor( private router: Router, location: Location,
        private chatService: ChatService,
        private jitsiService: JitsiService,
        private userService: UserService
    ) {
      this.location = location;
      this.chatService.callVisibilityChange
        .subscribe(callFrom => {
            console.log('admin layout call from', callFrom);
            if (callFrom) {
                this.userService.getLoggedUserDetail()
                    .subscribe(loggedUser => {
                        if (!loggedUser) {
                            console.log(`Invalid token, logged user data not fetched`);
                            return false;
                        }
                        this.userService.getUser(callFrom['fromUser'])
                            .subscribe(otherUser => {
                                swal({
                                    title: `${otherUser['fullName']} is calling`,
                                    text: `Click on accept to join session`,
                                    type: `info`,
                                    showCancelButton: true,
                                    cancelButtonColor: `#d33`,
                                    cancelButtonText: `reject`,
                                    confirmButtonColor: `#3085d6`,
                                    confirmButtonText: `accept`
                                }).then((result) => {
                                    if (result.value) {
                                        const jitsiSessionData = {
                                            loggedUser,
                                            otherUser,
                                            roomName: callFrom['roomName']
                                        }
                                        this.router.navigateByUrl(`/conference-student/${otherUser['_id']}`);
                                        window.setTimeout(() => this.jitsiService.joinSession(jitsiSessionData), 10000);
                                    } else {
                                        console.log('user select rejected');
                                        this.chatService.jitsiCallReject(otherUser._id, loggedUser._id, callFrom['roomName']);
                                    }
                                })
                            });
                    });
            }
        });
    }

    ngOnInit() {
        const elemMainPanel = <HTMLElement>document.querySelector('.main-panel');
        const elemSidebar = <HTMLElement>document.querySelector('.sidebar .sidebar-wrapper');
        this.location.subscribe((ev:PopStateEvent) => {
            this.lastPoppedUrl = ev.url;
        });
         this.router.events.subscribe((event:any) => {
            if (event instanceof NavigationStart) {
               if (event.url != this.lastPoppedUrl)
                   this.yScrollStack.push(window.scrollY);
           } else if (event instanceof NavigationEnd) {
               if (event.url == this.lastPoppedUrl) {
                   this.lastPoppedUrl = undefined;
                   window.scrollTo(0, this.yScrollStack.pop());
               }
               else
                   window.scrollTo(0, 0);
           }
        });
        this._router = this.router.events.filter(event => event instanceof NavigationEnd).subscribe((event: NavigationEnd) => {
             elemMainPanel.scrollTop = 0;
             elemSidebar.scrollTop = 0;
        });
        const html = document.getElementsByTagName('html')[0];
        if (window.matchMedia(`(min-width: 960px)`).matches && !this.isMac()) {
            let ps = new PerfectScrollbar(elemMainPanel);
            ps = new PerfectScrollbar(elemSidebar);
            html.classList.add('perfect-scrollbar-on');
        }
        else {
            html.classList.add('perfect-scrollbar-off');
        }
        this._router = this.router.events.filter(event => event instanceof NavigationEnd).subscribe((event: NavigationEnd) => {
          this.navbar.sidebarClose();
        });

        this.navItems = [
          { type: NavItemType.NavbarLeft, title: 'Dashboard', iconClass: 'fa fa-dashboard' },

          {
            type: NavItemType.NavbarRight,
            title: '',
            iconClass: 'fa fa-bell-o',
            numNotifications: 5,
            dropdownItems: [
              { title: 'Notification 1' },
              { title: 'Notification 2' },
              { title: 'Notification 3' },
              { title: 'Notification 4' },
              { title: 'Another Notification' }
            ]
          },
          {
            type: NavItemType.NavbarRight,
            title: '',
            iconClass: 'fa fa-list',

            dropdownItems: [
              { iconClass: 'pe-7s-mail', title: 'Messages' },
              { iconClass: 'pe-7s-help1', title: 'Help Center' },
              { iconClass: 'pe-7s-tools', title: 'Settings' },
               'separator',
              { iconClass: 'pe-7s-lock', title: 'Lock Screen' },
              { iconClass: 'pe-7s-close-circle', title: 'Log Out' }
            ]
          },
          { type: NavItemType.NavbarLeft, title: 'Search', iconClass: 'fa fa-search' },

          { type: NavItemType.NavbarLeft, title: 'Account' },
          {
            type: NavItemType.NavbarLeft,
            title: 'Dropdown',
            dropdownItems: [
              { title: 'Action' },
              { title: 'Another action' },
              { title: 'Something' },
              { title: 'Another action' },
              { title: 'Something' },
              'separator',
              { title: 'Separated link' },
            ]
          },
          { type: NavItemType.NavbarLeft, title: 'Log out' }
        ];
    }
    ngAfterViewInit() {
        this.runOnRouteChange();
        this.stuConf.changes.subscribe((comp: QueryList<ConferenceStudentComponent>) => {
            console.log(`student component`, comp);
        })
    }
    public isMap() {
        if (this.location.prepareExternalUrl(this.location.path()) === '/maps/fullscreen') {
            return true;
        } else {
            return false;
        }
    }
    runOnRouteChange(): void {
      if (window.matchMedia(`(min-width: 960px)`).matches && !this.isMac()) {
        const elemSidebar = <HTMLElement>document.querySelector('.sidebar .sidebar-wrapper');
        const elemMainPanel = <HTMLElement>document.querySelector('.main-panel');
        let ps = new PerfectScrollbar(elemMainPanel);
        ps = new PerfectScrollbar(elemSidebar);
        ps.update();
      }
    }
    isMac(): boolean {
        let bool = false;
        if (navigator.platform.toUpperCase().indexOf('MAC') >= 0 || navigator.platform.toUpperCase().indexOf('IPAD') >= 0) {
            bool = true;
        }
        return bool;
    }
}

孩子:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import '../../vendor/jitsi/external_api.js';
import { JitsiService } from 'app/services/jitsi.service.js';
import { UserService, UserSchema } from 'app/services/user.service.js';
import swal from 'sweetalert2';

declare var JitsiMeetExternalAPI: any;
declare const $: any;

@Component({
  selector: "app-conference-student-cmp",
  templateUrl: "conference-student.component.html"
})
export class ConferenceStudentComponent implements OnInit {
  roomName: string;
  tutor: UserSchema
  student: UserSchema;
  domain: string;
  options: any;
  api: any;
  hasActiveRoom: boolean;
  tutorId: string;
  conferenceJoined: boolean;

  constructor(
    private route: ActivatedRoute,
    private jitsiService: JitsiService,
    private userService: UserService
  ) { }

  ngOnInit() {
    this.conferenceJoined = false;
    // this.domain = "jitsi.liquidclouds.in";
    this.domain = 'meet.jit.si';
    this.route.paramMap.subscribe((params: ParamMap) => this.tutorId = params.get('id'));
    this.userService
      .getLoggedUserDetail()
      .subscribe(student => {
        // store student
        this.student = student;

        this.userService.getUser(this.tutorId)
          .subscribe((tutor: UserSchema) => {
            // store tutor
            this.tutor = tutor;
            const obj = { tutorId: this.tutor['_id'], studentId: this.student['_id'] };
            this.jitsiService.getActiveRoomForStudent(obj).subscribe(resp => {
              if (resp && resp['result'] && resp['result']['roomName']) {
                this.hasActiveRoom = true;
                this.roomName = resp['result']['roomName'];
              }
            });
          });
      });
  }

  joinSession() {
    this.options = {
      roomName: this.roomName,
      width: 800,
      height: 500,
      parentNode: document.querySelector('#jitsiVideo'),
      configOverwrite: {},
      interfaceConfigOverwrite: {
        // filmStripOnly: true,
        TOOLBAR_BUTTONS: [
          'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen',
          'hangup', 'profile', 'chat', 'recording'
        ],
      }
    };

    this.api = new JitsiMeetExternalAPI(this.domain, this.options);
    this.api.executeCommand('displayName', this.student['fullName']);

    this.api.addEventListeners({
      readyToClose: this.unload,
      participantLeft: this.handleParticipantLeft,
      participantJoined: this.handleParticipantJoined,
      videoConferenceJoined: this.handleVideoConferenceJoined,
      videoConferenceLeft: this.handleVideoConferenceLeft
    });

    this.conferenceJoined = true;
  }
  unload = () => {
    if (this.api instanceof JitsiMeetExternalAPI) {
      this.api.dispose();
    }
    $('#jitsiVideo').html('');
    this.conferenceJoined = false;
    this.hasActiveRoom = false;
  }
  handleParticipantLeft = (arg) => {
    this.jitsiService.getJitsiDetailByParticipantId(arg.id)
      .subscribe(async roomDetail => {
        if (!roomDetail) {
          console.log(`No room is joined by the participant id: ${arg.id}`);
          return false;
        } else {
          const participantDetail = roomDetail['participants'].filter(el => el.jitsiParticipantId === arg.id)[0];

          if (participantDetail) {
            switch (participantDetail.type) {
              case 'manager':
                console.log('Left participant is manager');
                break;
              case 'supervisor':
                console.log('Left participant is supervisor');
                break;
              case 'student':
                console.log('Left participant is student');
                break;
              case 'tutor':
                console.log('Left participant is tutor');
                this.api.dispose();
                this.conferenceJoined = false;
                this.hasActiveRoom = false;
                alert('Tutor left the session.');
                break;
              default:
                console.log('Left participant is not a valid type');
                break;
            }
          }
        }
      });
  }
  handleParticipantJoined = (arg) => {
    console.log('participant joined: ', arg, this.api);
  }
  handleVideoConferenceJoined = (arg) => {
    const obj = {
      participantId: arg.id,
      roomName: arg.roomName,
      tutorId: this.tutor['_id'],
      studentId: this.student['_id'],
      studentJoined: 'yes',
      joineeType: 'student',
    }
    // save new room
    this.jitsiService.updateJitsiRoomForStudent(obj);
  }
  handleVideoConferenceLeft = (arg) => {
  }
}

admin-layout.componet.html

<div class="wrapper">
    <div class="sidebar" data-color="rose" data-background-color="white" data-image="./assets/img/sidebar-1.jpg">

        <app-sidebar-cmp></app-sidebar-cmp>


        <div class="sidebar-background" style="background-image: url(assets/img/sidebar-1.jpg)"></div>
    </div>
    <div class="main-panel">
        <router-outlet></router-outlet>
        <div *ngIf="!isMap()">
            <app-footer-cmp></app-footer-cmp>
        </div>
    </div>
    <app-fixedplugin></app-fixedplugin>
</div>

0 个答案:

没有答案