2017-04-11 9 views
2

私は、角度2を使って3d "カードフリップ"を作成しています。親の 'card-flip'コンポーネントは、ネストされた 'card-flip-front'カード・フリップ・バック 'コンポーネントである。ng-contentを持つAngular2コンポーネントの "クローン"を作成する

<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タグ内のコンテンツも「クローン」に投影する必要があることです。問題は、最初のng-contentタグがコンテンツ投影にAngularによって使用され、ラベルなしの追加の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>

UPDATE:

[OK]を、ので、いくつかの類似した課題や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> 

基本的に、私たちは、テンプレート内に配置し、唯一のクラスのプロパティisOpenに基づいて、テンプレートの1つのインスタンスが表示されます*ngIf文で2個のng-containerのタグを使用してng-contentで単一の投影問題を回避することができます。

これはすべての問題を解決するわけではありませんが、同時に1つのコンテナしかレンダリングされないためです。だから、私は "元"の現在の位置を取得して、上記のリターンアニメーションの間に "クローン"をアニメーション化する場所を特定することはできません。

答えて

0

<card-flip><ng-content>を受け取った<card-flip>テンプレートの中に仲介コンポーネント<card-flip-content>があると思います。以下のような

何か:

@Component(
    selector = 'card-flip', 
    template = ` 
    <card-flip-content #theOne> 
     <ng-content /> 
    </card-flip-content> 
    <card-flip-content #theClone> 
     <ng-content /> 
    </card-flip-content> 
`) 

はその後#theOneと#theCloneに必要に応じてデータをバインドするだけ#theCloneをアニメーション化。 この方法では@Inputと@Outputを持つことができます。したがって、あるコンポーネントのアクションを親によって解釈されたままにしておき、他のコンポーネントに作用させることができます。

これは機能しますか?

+0

考えてくれてありがとうございますが、私は誤解の可能性があると思います。この例では、ng-contentを2回使用しています。最初のng-contentタグだけが投影されたコンテンツを含むので、主な問題は依然として残ります。 – Jbird

+2

このコンテンツの制限は、意図された動作です。ここでは、https://github.com/angular/angular/issues/7795で詳しく説明しています – Jbird

関連する問題