編集2:この問題は素晴らしいCDKチームによって修正されました!
編集:これは非常に奇妙な振る舞いのように思われるので、私は今のところ公式のCDKリポジトリに問題を追加しました。ただし、アイデアや回避策を自由に提案してください。
さまざまな種類の要素があり、*cdkDropList
ドラッグするときにさまざまなプラクホルダーの高さが必要です。配列にはプロパティを持つオブジェクトがあるため、type
これらの型をCSSクラスとして追加し、を使用して動的に追加しようとしました[ngClass]
。ただし、これらの動的に生成されたクラスは、「通常の」CSSクラスとして設定した場合とは動作が異なります。
これは、クラスを動的に設定するとどうなるかです。
プレースホルダーとdropList
重なり合う要素。関連するコードは次のとおりです。
example.component.ts
contentItems: ContentItem[] = [
{ type: 'text', /* more props */ },
{ type: 'text', /* more props */ },
{ type: 'image', /* more props */ }
];
example.component.html
<div *ngFor="let item of contentItems" class="editor-item" cdkDrag>
<div [ngClass]="['dropzone-placeholder', item.type]" *cdkDragPlaceholder>
<p>{{ 'EDITOR.INSERT HERE' | translate }}</p>
</div>
<app-language-tab-editor *ngIf="item.type === 'text'"></app-language-tab-editor>
<app-image-upload *ngIf="item.type === 'image'"></app-image-upload>
</div>
example.component.scss
$dropzone-placeholder-dark: #00973B;
$dropzone-placeholder-light: #00973B0D;
$text-placeholder-height: 135px;
$image-placeholder-height: 375px;
.dropzone-placeholder {
border: 1px dashed $dropzone-placeholder-dark;
color: $dropzone-placeholder-dark;
background: $dropzone-placeholder-light;
&.text {
height: $text-placeholder-height;
}
&.image {
height: $image-placeholder-height;
}
}
現在、2つの異なるタイプしかありませんが、目標は、後で追加するために簡単に拡張できるようにすることです。私もすでに代わりにclass="dropzone-placeholder {{ item.type }}"
同様に使用しようとし[class]="'dropzone-placeholder ' + item.type"
ましたが、役に立ちませんでした。
さらにテストした結果[ngClass]
、変数を使用しなくても、通常はを使用しても機能しないことがわかりました。使用も機能[ngClass]="['dropzone-placeholder', 'text']"
しませんでした。
これは予想される動作です。
プレースホルダーとの要素dropList
は重複せず、代わりに互いに適切に配置されます。現在、この動作はクラスを定期的に設定することによってのみ実現できますが、コードが将来乱雑に冗長になるため、HTMLを見るのはかなり不快です。
example.component.html
<div *ngFor="let item of contentItems" class="editor-item" cdkDrag>
<div *ngIf="item.type === 'text'">
<div class="dropzone-placeholder reorder text" *cdkDragPlaceholder>
<p>{{ 'EDITOR.INSERT HERE' | translate }}</p>
</div>
</div>
<div *ngIf="item.type === 'image'">
<div class="dropzone-placeholder reorder image" *cdkDragPlaceholder>
<p>{{ 'EDITOR.INSERT HERE' | translate }}</p>
</div>
</div>
<app-language-tab-editor *ngIf="item.type === 'text'"></app-language-tab-editor>
<app-image-upload *ngIf="item.type === 'image'"></app-image-upload>
</div>
クラスが従来の方法で設定されていないのに、CDKの動作が異なるのはなぜですか?そして、どうすれば上記の冗長な回避策を書かないようにできますか?
更新:この問題はCDK-Packageでネイティブに修正され、回避策は廃止されました。
@ Achilles1515による前述のGitHubの問題に対するこの回答で指摘されているように、現在、TSファイルでパッチを適用したコードを使用する回避策があります。これをネイティブに修正するCDKの更新に確実に注意してください。
関連するコードは次のとおりです。
import { CdkDragDrop, DragRef, moveItemInArray } from '@angular/cdk/drag-drop';
import { Component, EmbeddedViewRef} from '@angular/core';
DragRef.prototype._createPlaceholderElement = function(): HTMLElement {
const placeholderConfig = this._placeholderTemplate;
const placeholderTemplate = placeholderConfig
? placeholderConfig.template
: null;
let placeholder: HTMLElement;
if (placeholderTemplate) {
this._placeholderRef = placeholderConfig!.viewContainer.createEmbeddedView(
placeholderTemplate,
placeholderConfig!.context
);
this._placeholderRef.detectChanges(); // This is the missing line in the CDK
placeholder = getRootNode(this._placeholderRef, this._document);
} else {
placeholder = deepCloneNode(this._rootElement);
}
placeholder.classList.add('cdk-drag-placeholder');
return placeholder;
};
/** Creates a deep clone of an element. */
function deepCloneNode(node: HTMLElement): HTMLElement {
const clone = node.cloneNode(true) as HTMLElement;
const descendantsWithId = clone.querySelectorAll('[id]');
const descendantCanvases = node.querySelectorAll('canvas');
// Remove the `id` to avoid having multiple elements with the same id on the page.
clone.removeAttribute('id');
for (let i = 0; i < descendantsWithId.length; i++) {
descendantsWithId[i].removeAttribute('id');
}
// `cloneNode` won't transfer the content of `canvas` elements so we have to do it ourselves.
// We match up the cloned canvas to their sources using their index in the DOM.
if (descendantCanvases.length) {
const cloneCanvases = clone.querySelectorAll('canvas');
for (let i = 0; i < descendantCanvases.length; i++) {
const correspondingCloneContext = cloneCanvases[i].getContext('2d');
if (correspondingCloneContext) {
correspondingCloneContext.drawImage(descendantCanvases[i], 0, 0);
}
}
}
return clone;
}
function getRootNode(
viewRef: EmbeddedViewRef<any>,
_document: Document
): HTMLElement {
const rootNode: Node = viewRef.rootNodes[0];
if (rootNode.nodeType !== _document.ELEMENT_NODE) {
const wrapper = _document.createElement('div');
wrapper.appendChild(rootNode);
return wrapper;
}
return rootNode as HTMLElement;
}
これを私のコードに追加すると、で奇妙な動作が修正されました[ngClass]
。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加