Angular 如何获取动态创建的 div 的高度并将其发送到同级组件?
Angular how to get height of dynamically created div and send it to sibling component?
我有一个 parent
和 2 child components
如下所示
Parent-component.html
<child-component-1 [id]="id"></child-component-1>
<child-component-2></child-component-2>
child-component-1
有 ngb-carousel 组件向 user.And 显示警告和警报 由于 id
而创建此组件,其 result
来自 API
如下所示
child-component-1.ts
alertFound;
this.service.checkAlert(id).subscribe((result:any)=>{
if(result.alertFound){
this.alertFound=true;
}
})
child-component-1.html
<ngb-carousel #carousel *ngIf="alertFound" class="carousel-alert" [interval]="false" [wrap]="false"
[showNavigationIndicators]="false">
........................(Things go on here after result comes)
</ngb-carousel>
在child-component-2
中,我需要得到这个ngb-alert
的height
来对它存在的screen.If进行动态高度计算,我需要从中减去它window.innerheight
.
child-component-2.html
<div [style.height.px]="actualHeight"></div>
child-component-2.ts
this.actualHeight = window.innerHeight - 269;
有趣的是 child-component-1
当我试图像下面那样跟踪它时
@ViewChild('carousel', {read: ElementRef, static:false}) elementView: ElementRef;
ngAfterViewInit(){
console.log(this.elementView.nativeElement.offSetHeight);
//throws height of created carousel first,then if next id doesnt have alert still shows me the height which previously created
}
它显示之前创建的 carousel
高度,即使结果是 false
而 carousel
无法创建 moment.I 猜想发生这种情况是因为结果有时会非常晚了,有时 fast.To 监听 viewchild
上的检测 我发现像下面这样的东西完全按照我想要的方式工作并解决了发射 non-created 警报高度问题
@ViewChildren('carousel', {read: ViewContainerRef}) viewContainerRefs;
ngAfterViewInit() {
this.viewContainerRefs.changes.subscribe(item => {
if (item) {
console.log(item._results[0]._lContainer[0][0].offsetHeight);
}
})
}
现在的问题是将这个高度发送到 child-component-2,我应该在那里动态计算高度。
我考虑过 2 options.First 一个是在服务上创建主题,从 child-component-1
向它发射高度并在 child-component-2
上收听它,如下所示
service.ts
alertActive = new BehaviorSubject(0);
setAlertHeight(value:number){
this.alertActive.next(value)
}
child-component-1
ngAfterViewInit() {
this.viewContainerRefs.changes.subscribe(item => {
if (item) {
this.service.setAlertHeight(item._results[0]._lContainer[0][0].offsetHeight);
}
})
}
child-component-2
this.alertActive.subscribe(value=>{
if(value){
this.actualHeight-=value;
}
})
在上面的例子中,它会导致问题带来高度,即使警报未 created.I 从 child-2
和 child-1
登录控制台并注意到 child-2
打印到控制台,即使 child1 没有向它发出任何东西。
所以我考虑了另一种选择,通过@Output 将高度从 child-1 发送到 parent,然后通过 Input 发送到
child2 个赞
child-1
@Output() transferHeight: EventEmitter<any> = new EventEmitter();
this.viewContainerRefs.changes.subscribe(item => {
if (item) {
this.transferHeight.emit(item._results[0]._lContainer[0][0].offsetHeight);
}
})
parent
<child-component-1 (transferHeight)="transferedHeight($event)" [id]="id"></child-component-1>
<child-component-2 [transferredHeight]="transferredHeight"></child-component-2>
alertHeight;
transferedHeight(comingHeight){
this.alertHeight=comingHeight;
}
child-2
@Input() transferredHeight;
ngOnInit(){
this.actualHeight-=this.transferredHeight;
}
这个真的解决了我提到的问题 previously.But 如果轮播是在 child-2 之后创建的,因为延迟网络恢复,它 returns undefined.Therefore 我试过了使用 ngOnChanges 监听输入变量的变化,如下所示
ngOnChanges(changes: SimpleChanges) {
console.log(changes.transferredHeight.currentValue)
}
这个console.log虽然我实现了onChanges.So但没有打印任何东西我在等你help.If有一种方法可以从child-1中收听viewContainerRefs.changes
child-2 是最好的情况
这次尝试的原因:
alertActive = new BehaviorSubject(0);
setAlertHeight(value:number){
this.alertActive.next(value)
}
即使警报未处于活动状态也会触发要设置的高度是因为您使用了 BehaviorSubject
而不仅仅是 Subject
。 BehaviorSubject 提供初始值(在您的情况下为 0
),因此订阅者将在订阅后立即收到该初始值(或最新发出的值)。
所以你是在正确的轨道上,你只需要使用常规的 Subject
来代替,因为这样订阅者在 Subject
发出之前不会收到任何值。
因此您的服务可能如下所示:
private _alertActive = new Subject<number>();
get alertActive(): Observable<number> {
return this._alertActive.asObservable();
}
setAlertHeight(height: number) {
this._alertActive.next(height);
}
(请注意,Subject
是私有成员,但通过 getter 作为 Observable 公开。一般来说,订阅者不应该访问原始 Subject,除非他们也从中散发出价值。)
你的 child-2 组件会像这样订阅它:
this.service.alertActive.subscribe((height: number) => {
this.actualHeight -= height;
});
您使用 ViewChildren
并订阅它的 changes
也是正确的,但如果您引用 ElementRef
而不是 ViewContainerRef
可能会更简单]s。看起来像这样:
import { NgbCarousel } from "@ng-bootstrap/ng-bootstrap";
@ViewChildren(NgbCarousel, { read: ElementRef }) carousels: QueryList<ElementRef>;
ngAfterViewInit() {
this.carousels.changes.subscribe((els: QueryList<ElementRef>) => {
const height = els.first ? els.first.nativeElement.offsetHeight : 0;
this.service.setAlertHeight(height);
});
}
Here's a StackBlitz 显示它使用这种方法。
我有一个 parent
和 2 child components
如下所示
Parent-component.html
<child-component-1 [id]="id"></child-component-1>
<child-component-2></child-component-2>
child-component-1
有 ngb-carousel 组件向 user.And 显示警告和警报 由于 id
而创建此组件,其 result
来自 API
如下所示
child-component-1.ts
alertFound;
this.service.checkAlert(id).subscribe((result:any)=>{
if(result.alertFound){
this.alertFound=true;
}
})
child-component-1.html
<ngb-carousel #carousel *ngIf="alertFound" class="carousel-alert" [interval]="false" [wrap]="false"
[showNavigationIndicators]="false">
........................(Things go on here after result comes)
</ngb-carousel>
在child-component-2
中,我需要得到这个ngb-alert
的height
来对它存在的screen.If进行动态高度计算,我需要从中减去它window.innerheight
.
child-component-2.html
<div [style.height.px]="actualHeight"></div>
child-component-2.ts
this.actualHeight = window.innerHeight - 269;
有趣的是 child-component-1
当我试图像下面那样跟踪它时
@ViewChild('carousel', {read: ElementRef, static:false}) elementView: ElementRef;
ngAfterViewInit(){
console.log(this.elementView.nativeElement.offSetHeight);
//throws height of created carousel first,then if next id doesnt have alert still shows me the height which previously created
}
它显示之前创建的 carousel
高度,即使结果是 false
而 carousel
无法创建 moment.I 猜想发生这种情况是因为结果有时会非常晚了,有时 fast.To 监听 viewchild
上的检测 我发现像下面这样的东西完全按照我想要的方式工作并解决了发射 non-created 警报高度问题
@ViewChildren('carousel', {read: ViewContainerRef}) viewContainerRefs;
ngAfterViewInit() {
this.viewContainerRefs.changes.subscribe(item => {
if (item) {
console.log(item._results[0]._lContainer[0][0].offsetHeight);
}
})
}
现在的问题是将这个高度发送到 child-component-2,我应该在那里动态计算高度。
我考虑过 2 options.First 一个是在服务上创建主题,从 child-component-1
向它发射高度并在 child-component-2
上收听它,如下所示
service.ts
alertActive = new BehaviorSubject(0);
setAlertHeight(value:number){
this.alertActive.next(value)
}
child-component-1
ngAfterViewInit() {
this.viewContainerRefs.changes.subscribe(item => {
if (item) {
this.service.setAlertHeight(item._results[0]._lContainer[0][0].offsetHeight);
}
})
}
child-component-2
this.alertActive.subscribe(value=>{
if(value){
this.actualHeight-=value;
}
})
在上面的例子中,它会导致问题带来高度,即使警报未 created.I 从 child-2
和 child-1
登录控制台并注意到 child-2
打印到控制台,即使 child1 没有向它发出任何东西。
所以我考虑了另一种选择,通过@Output 将高度从 child-1 发送到 parent,然后通过 Input 发送到 child2 个赞
child-1
@Output() transferHeight: EventEmitter<any> = new EventEmitter();
this.viewContainerRefs.changes.subscribe(item => {
if (item) {
this.transferHeight.emit(item._results[0]._lContainer[0][0].offsetHeight);
}
})
parent
<child-component-1 (transferHeight)="transferedHeight($event)" [id]="id"></child-component-1>
<child-component-2 [transferredHeight]="transferredHeight"></child-component-2>
alertHeight;
transferedHeight(comingHeight){
this.alertHeight=comingHeight;
}
child-2
@Input() transferredHeight;
ngOnInit(){
this.actualHeight-=this.transferredHeight;
}
这个真的解决了我提到的问题 previously.But 如果轮播是在 child-2 之后创建的,因为延迟网络恢复,它 returns undefined.Therefore 我试过了使用 ngOnChanges 监听输入变量的变化,如下所示
ngOnChanges(changes: SimpleChanges) {
console.log(changes.transferredHeight.currentValue)
}
这个console.log虽然我实现了onChanges.So但没有打印任何东西我在等你help.If有一种方法可以从child-1中收听viewContainerRefs.changes
child-2 是最好的情况
这次尝试的原因:
alertActive = new BehaviorSubject(0);
setAlertHeight(value:number){
this.alertActive.next(value)
}
即使警报未处于活动状态也会触发要设置的高度是因为您使用了 BehaviorSubject
而不仅仅是 Subject
。 BehaviorSubject 提供初始值(在您的情况下为 0
),因此订阅者将在订阅后立即收到该初始值(或最新发出的值)。
所以你是在正确的轨道上,你只需要使用常规的 Subject
来代替,因为这样订阅者在 Subject
发出之前不会收到任何值。
因此您的服务可能如下所示:
private _alertActive = new Subject<number>();
get alertActive(): Observable<number> {
return this._alertActive.asObservable();
}
setAlertHeight(height: number) {
this._alertActive.next(height);
}
(请注意,Subject
是私有成员,但通过 getter 作为 Observable 公开。一般来说,订阅者不应该访问原始 Subject,除非他们也从中散发出价值。)
你的 child-2 组件会像这样订阅它:
this.service.alertActive.subscribe((height: number) => {
this.actualHeight -= height;
});
您使用 ViewChildren
并订阅它的 changes
也是正确的,但如果您引用 ElementRef
而不是 ViewContainerRef
可能会更简单]s。看起来像这样:
import { NgbCarousel } from "@ng-bootstrap/ng-bootstrap";
@ViewChildren(NgbCarousel, { read: ElementRef }) carousels: QueryList<ElementRef>;
ngAfterViewInit() {
this.carousels.changes.subscribe((els: QueryList<ElementRef>) => {
const height = els.first ? els.first.nativeElement.offsetHeight : 0;
this.service.setAlertHeight(height);
});
}
Here's a StackBlitz 显示它使用这种方法。