英文:
Angular button directive incorrectly appending child element
问题
我使用这个按钮加载指令。我的问题是,当使用该指令时,它将进度加载器附加在按钮下方,而不是在按钮内部。
我已经在this.elementRef.nativeElement
上进行了控制台日志记录,它返回了正确的按钮元素。
button-loader.directive.ts
import { Directive, ElementRef, Input, ViewContainerRef, Renderer2 } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatProgressBar } from '@angular/material/progress-bar';
@Directive({
selector: '[buttonLoader]'
})
export class ButtonLoaderDirective {
progressElement: any;
@Input() set buttonLoader(value: boolean) {
this.toggle(value);
}
constructor(
private viewContainerRef: ViewContainerRef,
private matButton: MatButton,
private renderer: Renderer2,
private elementRef: ElementRef) {
this.loadComponent();
}
loadComponent() {
this.viewContainerRef.clear();
// 创建组件
const matProgress = this.viewContainerRef.createComponent(MatProgressBar);
matProgress.instance.mode = 'indeterminate';
// 将它移动
this.progressElement = matProgress.injector.get(MatProgressBar)._elementRef.nativeElement
this.renderer.appendChild(this.elementRef.nativeElement, this.progressElement);
// 添加自定义类
this.elementRef.nativeElement.classList.add('mat-load-button');
}
toggle(condition: boolean) {
condition ? this.show() : this.hide()
}
show() {
this.progressElement.style.opacity = '0.7';
this.matButton.disabled = true;
}
hide() {
this.progressElement.style.opacity = '0';
this.matButton.disabled = false;
}
}
HTML
<button
[buttonLoader]="true"
mat-raised-button
color="primary"
>
Save
</button>
当前的显示方式
这是我想要的显示方式
英文:
I'm using this loading directive for a button. My problem is when using the directive it appends the progress loader below the button, not inside of it.
I've console logged the this.elementRef.nativeElement
and it returns the correct button element.
button-loader.directive.ts
import { Directive, ElementRef, Input, ViewContainerRef, Renderer2 } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatProgressBar } from '@angular/material/progress-bar';
@Directive({
selector: '[buttonLoader]'
})
export class ButtonLoaderDirective {
progressElement: any;
@Input() set buttonLoader(value: boolean) {
this.toggle(value);
}
constructor(
private viewContainerRef: ViewContainerRef,
private matButton: MatButton,
private renderer: Renderer2,
private elementRef: ElementRef) {
this.loadComponent();
}
loadComponent() {
this.viewContainerRef.clear();
// Create Component
const matProgress = this.viewContainerRef.createComponent(MatProgressBar);
matProgress.instance.mode = 'indeterminate';
// Move it
this.progressElement = matProgress.injector.get(MatProgressBar)._elementRef.nativeElement
this.renderer.appendChild(this.elementRef.nativeElement, this.progressElement);
// Add custom class
this.elementRef.nativeElement.classList.add('mat-load-button');
}
toggle(condition: boolean) {
condition ? this.show() : this.hide()
}
show() {
this.progressElement.style.opacity = '0.7';
this.matButton.disabled = true;
}
hide() {
this.progressElement.style.opacity = '0';
this.matButton.disabled = false;
}
}
HTML
<button
[buttonLoader]="true"
mat-raised-button
color="primary"
>
Save
</button>
Currently how it looks
Here's how I want it to look
答案1
得分: 2
您的指令已经生效。progressbar
具有正确的“parent”。我只修改了 progressbar
的样式,添加了 position: absolute;
以及当前位置和宽度:
更新后的指令
import { Directive, ElementRef, Input, ViewContainerRef, Renderer2 } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatProgressBar } from '@angular/material/progress-bar';
@Directive({
selector: '[buttonLoader]'
})
export class ButtonLoaderDirective {
progressElement: any;
@Input() set buttonLoader(value: boolean) {
this.toggle(value);
}
constructor(
private viewContainerRef: ViewContainerRef,
private matButton: MatButton,
private renderer: Renderer2,
private elementRef: ElementRef) {
this.loadComponent();
}
loadComponent() {
this.viewContainerRef.clear();
// 创建组件
const matProgress = this.viewContainerRef.createComponent(MatProgressBar);
matProgress.instance.mode = 'indeterminate';
// 移动组件
this.progressElement = matProgress.injector.get(MatProgressBar)._elementRef.nativeElement
this.renderer.appendChild(this.elementRef.nativeElement, this.progressElement);
// 添加自定义类
this.elementRef.nativeElement.classList.add('mat-load-button');
}
toggle(condition: boolean) {
condition ? this.show() : this.hide()
}
show() {
this.progressElement.style.opacity = '0.7';
this.progressElement.style.position = "absolute"
this.matButton.disabled = true;
this.progressElement.style.bottom = "10px";
this.progressElement.style.width = "calc(100% - 10px)";
}
hide() {
this.progressElement.style.opacity = '0';
this.matButton.disabled = false;
}
}
HTML
<button
style="height: 80px"
mat-raised-button
color="primary"
[buttonLoader]="true"
>
My Button
</button>
这是完整的 Stackblitz 示例。
这是结果图像:
英文:
Your directive works. The progressbar
has the right "parent". I only have modified the progressbar
style with position: absolute;
and the current position + width:
Updated directive
import { Directive, ElementRef, Input, ViewContainerRef, Renderer2 } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatProgressBar } from '@angular/material/progress-bar';
@Directive({
selector: '[buttonLoader]'
})
export class ButtonLoaderDirective {
progressElement: any;
@Input() set buttonLoader(value: boolean) {
this.toggle(value);
}
constructor(
private viewContainerRef: ViewContainerRef,
private matButton: MatButton,
private renderer: Renderer2,
private elementRef: ElementRef) {
this.loadComponent();
}
loadComponent() {
this.viewContainerRef.clear();
// Create Component
const matProgress = this.viewContainerRef.createComponent(MatProgressBar);
matProgress.instance.mode = 'indeterminate';
// Move it
this.progressElement = matProgress.injector.get(MatProgressBar)._elementRef.nativeElement
this.renderer.appendChild(this.elementRef.nativeElement, this.progressElement);
// Add custom class
this.elementRef.nativeElement.classList.add('mat-load-button');
}
toggle(condition: boolean) {
condition ? this.show() : this.hide()
}
show() {
this.progressElement.style.opacity = '0.7';
this.progressElement.style.position = "absolute"
this.matButton.disabled = true;
this.progressElement.style.bottom = "10px";
this.progressElement.style.width = "calc(100% - 10px)"
}
hide() {
this.progressElement.style.opacity = '0';
this.matButton.disabled = false;
}
}
HTML
<button
style="height: 80px"
mat-raised-button
color="primary"
[buttonLoader]="true"
>
My Button
</button>
Here is the complete Stackblitz example.
Here the result:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论