簡體   English   中英

當我使用 @ViewChild 在 Angular 組件之間共享布爾數據時,我得到了未定義的屬性

[英]I get undefined property when I share boolean data between Angular components using @ViewChild

我有一個名為RedirectUserToMobileAppComponent的組件,我想與app.component共享一個名為enableLoginForm的布爾屬性。 當我執行時,我收到此錯誤:

enableLoginFormapp.componentngAfterViewInit上的未定義屬性

這是RedirectUserToMobileAppComponent組件:

    import {
        Component,
        ComponentFactoryResolver,
        ComponentRef,
        Inject,
        Input,
        OnInit,
        Output,
        ViewChild,
        ViewContainerRef,
    } from '@angular/core';
    import { Observable, Subscription } from 'rxjs';
    import { filter, map, pluck, tap } from 'rxjs/operators';
    import { ActivatedRoute, Router } from '@angular/router';
    import { MAT_DIALOG_SCROLL_STRATEGY_FACTORY } from '@angular/material/dialog';

    @Component({
        selector: 'redirect-user-to-mobile-app',
        templateUrl: './redirect-user-to-mobile-app.component.html',
        styleUrls: ['./redirect-user-to-mobile-app.component.sass'],
    })
    export class RedirectUserToMobileAppComponent implements OnInit {
        constructor(
        ) {}
        enableLoginForm = false;
        ngOnInit(): void {}
    
        OnLogin(): void {
            this.enableLoginForm = true;
            this.router.navigate(['../login']);
        }
        
    }

這是app.component

    import {
    Component,
    HostListener,
    OnDestroy,
    OnInit,
    ViewChild,
    AfterViewInit,
} from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { FirebaseService } from './services/firebase/firebase.service';
import {
    SnakeMessage,
    SnakeMessageService,
} from './services/snakeMessage/snakeMessage.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Subscription } from 'rxjs';
import { StorageService } from './services/storage/storage.service';
import { AuthService } from './services/auth/auth.service';
import { RedirectUserToMobileAppComponent } from './redirect-user-to-mobile-app/redirect-user-to-mobile-app.component';

@Component({
    selector: 'app-component',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
    favIcon: HTMLLinkElement = document.querySelector('#appIcon');
    private snakeMessageSub: Subscription;
    isLoading = true;
    isLogged: boolean;

    @ViewChild(RedirectUserToMobileAppComponent)
    redirectComponent!: RedirectUserToMobileAppComponent;

    constructor(
        private matIconRegistry: MatIconRegistry,
        private firebaseService: FirebaseService,
        private snakeMessageService: SnakeMessageService,
        private _snackBar: MatSnackBar,
        private storageService: StorageService,
        private domSanitizer: DomSanitizer,
        private authService: AuthService
    ) {
        this.registerCustomIcons();
        this.storageService.initDB();
        this.storageService.onLoaded$.subscribe((loaded) => {
            if (loaded) {
                this.isLoading = false;
            }
        });
        this.isLogged = this.authService.isLoggedIn;
    }

    ngAfterViewInit() {
        if (this.redirectComponent.enableLoginForm) {
            this._is = this.redirectComponent.enableLoginForm;
        }
    }

    ngOnInit(): void {
        this.snakeMessageSub = this.snakeMessageService.messageSub.subscribe(
            (snakeMessage: SnakeMessage) => {
                this._snackBar.open(snakeMessage.message, snakeMessage.action, {
                    duration: 3000,
                    horizontalPosition: 'center',
                    verticalPosition: 'top',
                });
            }
        );
    }

這是我的 app.component.html

<ng-container *ngIf="!isLoading">
<ng-container *ngIf="isMobileDevice() && !isLogged">
    <redirect-user-to-mobile-app> </redirect-user-to-mobile-app>
    <router-outlet
        *ngIf="enableLoginForm"
    ></router-outlet>
</ng-container>

<router-outlet *ngIf="!isMobileDevice()"></router-outlet>

這是您使用 ViewChild 的方式:

@ViewChild('templateId', { static: false }) redirectComponent: RedirectUserToMobileAppComponent;

您應該在模板部分設置 templateId :

<redirect-user-to-mobile-app #templateId> ... </redirect-user-to-mobile-app>

編輯:雖然我同意 skyBlue,但您應該使用服務在組件之間共享數據

ViewChild返回對 HTML 元素引用

我將從angular.io引用:

配置視圖查詢的屬性裝飾器。 變更檢測器在視圖 DOM 中查找與選擇器匹配的第一個元素或指令。 如果視圖 DOM 更改,並且新的子項與選擇器匹配,則該屬性會更新。

所以你不能用ViewChild訪問它的控制器變量。

我對您的建議是使用service來傳遞數據。

我改變了方法,我使用了 @Output() 組件,它工作正常:

這是更改方法后的RedirectUserToMobileAppComponent組件:

    import {
    Component,
    ComponentFactoryResolver,
    ComponentRef,
    Inject,
    Input,
    OnChanges,
    OnInit,
    Output,
    SimpleChanges,
    ViewChild,
    ViewContainerRef,
    EventEmitter,
} from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import { filter, map, pluck, tap } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router';
import { MAT_DIALOG_SCROLL_STRATEGY_FACTORY } from '@angular/material/dialog';
@Component({
    selector: 'yobi-redirect-user-to-mobile-app',
    templateUrl: './redirect-user-to-mobile-app.component.html',
    styleUrls: ['./redirect-user-to-mobile-app.component.sass'],
})
export class RedirectUserToMobileAppComponent implements OnInit {
    constructor(
        private router: Router,
        private componentFactoryResolver: ComponentFactoryResolver
    ) {}

    @Output() _enableLoginForm: EventEmitter<boolean> = new EventEmitter();
    variable: any;
    login: boolean;
    enableLoginForm = false;
    enableSignupForm = false;
    ngOnInit(): void {}

    sendDataToParent() {
        this.enableLoginForm = true;
        this._enableLoginForm.emit(this.enableLoginForm);
        console.log(this.enableLoginForm + ' From redirect ');
    }

我將此添加到RedirectUserToMobileAppComponent.html

<a class="login-text" (click)="sendDataToParent()">
          Login
      </a>

我將此代碼添加到app.component

receiveChildData($event) {
    this.enableLoginForm = $event;
}

我將此代碼添加到 app.component.html :

<redirect-user-to-mobile-app
        (_enableLoginForm)="receiveChildData($event)"
    >
    </redirect-user-to-mobile-app>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM