我正在使用角度2创建一个3D“卡片翻转”。父级“卡片翻转”组件包含嵌套的“卡片翻转前”和“卡片翻转”组件。
<card-flip card-flip-id="demo-1" class="grid_col-6">
<card-flip-front class="card">
<div class="card__inner">
Card Front
</div>
</card-flip-front>
<card-flip-back class="card">
<div class="card__inner">
Card Back
</div>
</card-flip-back>
</card-flip>
我想创建一个卡片翻转前组件的“克隆”,内容投影和数据绑定。 “克隆”将用于动画,“原始”将保留在隐藏的原始位置。这样我就可以参考“返回到原始位置时”克隆“应该动画的位置(即使用户滚动窗口或调整窗口大小)。
我面临的主要挑战是我需要将ng-content
标签内的内容投射到“克隆”中。问题是Angular将使用第一个ng-content
标记进行内容投影,而其他未标记的ng-content
标记将为空(我知道这是预期的行为)。
有人可能会问,“为什么不在DOM中创建一个愚蠢的,静态的元素副本?”。我想避免这种情况,以便注入数据的嵌套组件和数据绑定(从而修改元素的维度)将继续有效。
这是我到目前为止的工作,它通过ComponentFactory创建CardFlipFront组件的实例作为“克隆”,并简单地插入“原始”CardFlipFront的innerHTML。
import {
Component,
ComponentFactory,
ComponentFactoryResolver,
ComponentRef,
ContentChild,
Inject,
Input,
OnInit,
ViewChild,
ViewContainerRef
} from '@angular/core';
import { CardFlipFrontComponent } from './card-flip-front.component';
import { CardFlipBackComponent } from './card-flip-back.component';
import { CardFlipService } from './card-flip.service';
@Component({
selector: 'card-flip',
templateUrl: './card-flip.component.html',
styleUrls: ['./card-flip.component.css'],
entryComponents: [
CardFlipFrontComponent
]
})
export class CardFlipComponent implements OnInit {
@Input('card-flip-id') public id: string;
@ContentChild(CardFlipFrontComponent) private front: CardFlipFrontComponent;
@ContentChild(CardFlipBackComponent) private back: CardFlipBackComponent;
@ViewChild('frontCloneContainer', { read: ViewContainerRef }) private frontCloneContainer: ViewContainerRef;
private frontComponentRef: ComponentFactory<CardFlipFrontComponent>;
private frontClone: ComponentRef<CardFlipFrontComponent>;
constructor(
@Inject(CardFlipService) private _cardFlipService: CardFlipService,
private _componentFactoryResolver: ComponentFactoryResolver
) {
this.frontComponentRef = this._componentFactoryResolver.resolveComponentFactory(CardFlipFrontComponent);
}
ngOnInit() {
this._cardFlipService.register(this.id);
}
ngAfterViewInit() {
// Create a card-flip-front component instance to serve as a "clone"
this.frontClone = this.frontCloneContainer.createComponent(this.frontComponentRef);
// Copy the innerHTML of the "original" into the "clone"
this.frontClone.instance.el.nativeElement.innerHTML = this.front.el.nativeElement.innerHTML;
}
ngOnDestroy() {
this.frontClone.destroy();
}
}
<ng-content select="card-flip-front"></ng-content>
<ng-container #frontCloneContainer></ng-container>
<ng-content select="card-flip-back"></ng-content>
import {
Component,
ElementRef,
HostBinding,
Input,
OnInit,
Renderer
} from '@angular/core';
@Component({
selector: 'card-flip-front',
templateUrl: './card-flip-front.component.html',
styleUrls: ['./card-flip-front.component.css']
})
export class CardFlipFrontComponent implements OnInit {
constructor(private _el: ElementRef, private _renderer: Renderer) { }
public get el(): ElementRef {
return this._el;
}
public get renderer(): Renderer {
return this._renderer;
}
ngOnInit() { }
}
<ng-content></ng-content>
更新
好的,所以在阅读了一些类似的挑战和github issue here后,我尝试了以下内容。
<ng-template #frontTemplate>
<ng-content select="card-flip-front"></ng-content>
</ng-template>
<ng-container *ngIf="isOpen == true" #front1>
<ng-container *ngTemplateOutlet="frontTemplate"></ng-container>
</ng-container>
<ng-container *ngIf="isOpen == false" #front2>
<ng-container *ngTemplateOutlet="frontTemplate"></ng-container>
</ng-container>
<ng-content select="card-flip-back"></ng-content>
基本上,我们可以通过将ng-content
置于模板中并使用两个带有ng-container
语句的*ngIf
标记来解决单个投影问题,该语句只会显示一个基于类属性isOpen
的模板。
这并不能解决整个问题,因为在任何给定时间只会呈现一个容器。因此,我无法获得“原始”的当前位置,以确定在上述返回动画期间将“克隆”设置为动画的位置。
答案 0 :(得分:0)
我认为您可以在<card-flip-content>
模板中设置一个中间组件<card-flip>
,该组件是重复的,并且会收到<ng-content>
的{{1}}。
类似的东西:
<card-flip>
然后根据需要将数据绑定到#theOne和#theClone,并仅动画#theClone。 这种方式可以有@Input和@Output,从而让一个组件的动作由父级解释,以便作用于另一个组件。
那会有用吗?