首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在按钮中显示微调器的angular指令

在按钮中显示微调器的angular指令
EN

Stack Overflow用户
提问于 2018-08-14 01:16:46
回答 2查看 5.5K关注 0票数 6

我正在尝试编写一个指令来修改一个按钮,以便在服务器操作进行时显示一个微调器按钮。

代码语言:javascript
复制
<button type="submit" waitingButton (click)="submit($event)">
 {{submitBtnText}}
</button>

到目前为止,我已经能够显示微调器,但我不知道如何捕获单击事件的结果以将其切换回正常状态。

这是一条指令:

代码语言:javascript
复制
import {
  Directive,
  ElementRef,
  HostListener,
  OnInit,
  Renderer2,
  ComponentFactoryResolver,
  ViewContainerRef
} from '@angular/core';
import { MatSpinner } from '@angular/material';


@Directive({
  selector: '[bcnWaitingButton]'
})
export class BCNWaitingButtonDirective implements OnInit {


  constructor(
    private el: ElementRef, 
    private renderer: Renderer2, 
    private componentFactoryResolver: ComponentFactoryResolver, 
    public vcRef: ViewContainerRef) {

  }

  ngOnInit(): void {
    
  }

  @HostListener('click', ['$event']) onClick(e): void {
    // Create the spinner
    const factory = this.componentFactoryResolver.resolveComponentFactory(MatSpinner);
    const componentRef = this.vcRef.createComponent(factory);
    const spinner: MatSpinner = componentRef.instance;
    
    // Configure the spinner
    spinner.strokeWidth = 3;
    spinner.diameter = 24;

    // Set the button to disabled
    this.renderer.setAttribute(this.el.nativeElement, 'disabled', 'true');
    
    // Apply new styles
    const span: ElementRef = this.el.nativeElement.querySelector('.mat-button-wrapper');
    this.renderer.setStyle(span, 'display', 'flex');
    this.renderer.setStyle(span, 'align-items', 'center');
    this.renderer.setStyle(span, 'justify-content', 'center');
    this.renderer.setStyle(spinner._elementRef.nativeElement, 'margin-top', '0px');
    this.renderer.setStyle(spinner._elementRef.nativeElement, 'margin-left', '5px');

    // Append the spinner
    this.renderer.appendChild(this.el.nativeElement.firstChild, spinner._elementRef.nativeElement);
  }
}

你有什么建议吗?我是否应该有一个带有提交回调的@Input,这样我就可以从指令的onClick函数中调用它?

EN

回答 2

Stack Overflow用户

发布于 2019-01-12 05:17:59

下面是一个完整的工作指令,用于将材料按钮的文本替换为MatSpinner,然后在操作完成后返回到文本。它利用了前两个答案的一部分:

代码语言:javascript
复制
import {
  ComponentFactoryResolver, Directive, Input, OnChanges, OnInit, Renderer2, SimpleChanges, ViewContainerRef
} from '@angular/core';
import { ElementRef } from '@angular/core';
import { MatSpinner } from '@angular/material';

@Directive({
  selector: 'button[appShowSpinner]'
})
export class SpinnerButtonDirective implements OnInit, OnChanges {
  // tslint:disable-next-line:no-input-rename
  @Input('appShowSpinner') showSpinner: boolean;
  originalInnerText: string;
  spinner: MatSpinner;

  constructor(
    private el: ElementRef,
    private renderer: Renderer2,
    private viewContainerRef: ViewContainerRef,
    private componentFactoryResolver: ComponentFactoryResolver
  ) { }

  ngOnInit() {
    // Record the button's original text
    this.originalInnerText = this.el.nativeElement.innerText;

    // Set the button to maintain the same dimensions, even once we put the spinner inside.
    this.el.nativeElement.style.width = `${(this.el.nativeElement as HTMLElement).offsetWidth}px`;
    this.el.nativeElement.style.height = `${(this.el.nativeElement as HTMLElement).offsetHeight}px`;

    // Create the spinner
    const factory = this.componentFactoryResolver.resolveComponentFactory(MatSpinner);
    const componentRef = this.viewContainerRef.createComponent(factory);
    this.spinner = componentRef.instance;

    // Configure the spinner
    this.spinner.strokeWidth = 3;
    this.spinner.diameter = 24;

    // Hide the spinner
    this.renderer.setStyle(this.spinner._elementRef.nativeElement, 'display', 'none');

    // Apply new styles to the button content's container
    const span = this.el.nativeElement.querySelector('.mat-button-wrapper') as HTMLSpanElement;
    this.renderer.setStyle(span, 'display', 'flex');
    this.renderer.setStyle(span, 'align-items', 'center');
    this.renderer.setStyle(span, 'justify-content', 'center');
  }

  ngOnChanges(changes: SimpleChanges) {
    if (typeof(changes.showSpinner) === 'object' && !changes.showSpinner.isFirstChange()) {
      if (changes.showSpinner.currentValue === true) {
        // Clear the button's text
        const span = this.el.nativeElement.querySelector('.mat-button-wrapper') as HTMLSpanElement;
        span.innerText = '';

        // Append the spinner
        this.renderer.appendChild(this.el.nativeElement.firstChild, this.spinner._elementRef.nativeElement);

        // Show the spinner
        this.renderer.setStyle(this.spinner._elementRef.nativeElement, 'display', 'inherit');
      }

      if (changes.showSpinner.currentValue === false) {
        // Hide the spinner
        this.renderer.setStyle(this.spinner._elementRef.nativeElement, 'display', 'none');

        // Remove the spinner
        this.renderer.removeChild(this.el.nativeElement.firstChild, this.spinner._elementRef.nativeElement);

        const span = this.el.nativeElement.querySelector('.mat-button-wrapper') as HTMLSpanElement;
        span.innerText = this.originalInnerText;
      }

      this.el.nativeElement.disabled = changes.showSpinner.currentValue;
    }
  }
}

使用指令:

代码语言:javascript
复制
<button [appShowSpinner]="isSaving" mat-raised-button>
  Submit
</button>
票数 10
EN

Stack Overflow用户

发布于 2018-08-14 04:26:09

我刚刚做了一个工作正常的例子(虽然我不能在stackblitz中使用material微调器,因为依赖错误),但这应该可以指导你:

代码语言:javascript
复制
import { Directive, Input, OnChanges } from '@angular/core';
import { ElementRef } from '@angular/core';

@Directive({
  selector: '[spinnerButton]'
})
export class SpinnerButtonDirective {
@Input('spinnerButton') isWaiting: boolean;
  originalInnerText: string;
  constructor( private el: ElementRef ) { }

  ngOnInit(){
    // Save the original button text so I can restore it when waiting ends
    this.originalInnerText = this.el.nativeElement.innerText;
  }

  ngOnChanges() {
    if (this.isWaiting) {
      this.el.nativeElement.innerText = 'waiting...';
    } else {
      if (this.el.nativeElement.innerText == 'waiting...') {
        this.el.nativeElement.innerText = this.originalInnerText;
      }
    }
    this.el.nativeElement.disabled = this.isWaiting;
  }
}

在你的html中,

代码语言:javascript
复制
<button (click)="getData()" [spinnerButton]="isWaiting">Get Data</button>

然后,您唯一需要做的就是在代码中(通常在getData()函数中)将isWaiting设置为true或false

演示:https://stackblitz.com/edit/angular-rb5vmu

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51827486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档