![](/img/trans.png)
[英]Why am I getting an undefined error when using ngIf and ViewChild together
[英]I get undefined property when I share boolean data between Angular components using @ViewChild
我有一個名為RedirectUserToMobileAppComponent
的組件,我想與app.component
共享一個名為enableLoginForm
的布爾屬性。 當我執行時,我收到此錯誤:
enableLoginForm是app.component中ngAfterViewInit上的未定義屬性
這是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.