首页 > 解决方案 > @ng-bootstrap/ng-bootstrap NgbModalModule 模态中的 Angula6 ViewChild 返回 undefined

问题描述

我成功地使用了 ng bootstrap,特别是模态模块来显示模态形式。这是一个包含电子邮件和消息输入字段以及提交按钮的联系表单。我正在使用的 ngbootstrap 模块是https://ng-bootstrap.github.io/#/components/modal/examples这显示得很好。我想要做的是,当用户单击“发送”按钮(请参阅下面的模板代码)时,该按钮将被禁用并说“发送...”。换句话说,我正在尝试操作属性视图模式组件。

我已经查看了以下问题,但没有任何建议有效:

Angular 2 @ViewChild 注释返回未定义 如何在 Angular 2 中获取与 ElementRef 关联的组件的引用

但是无论如何,当我尝试在我的组件中使用时,我会得到“未定义”

@ViewChild('submitButton') submitButton: ElementRef;

连同我模板中的这个 html

<button #submitButton
   id="submitButton"
   class="btn btn-success w-100"
   [disabled]="!contactForm.valid"
>Send</button>

这是完整的组件代码(我试图访问 submitButton 的地方在 method 中onSubmit()):

import {
    Component,
    OnInit,
    Renderer2,
    ViewChild,
    ElementRef,
    AfterViewInit
} from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';

import { ContactService } from '../../services/contact.service';

@Component({
    selector: 'app-contact-modal',
    templateUrl: './contact-modal.component.html'
})
export class ContactModalComponent implements OnInit, AfterViewInit {

    closeResult: string;
    contactForm: FormGroup;
    //@ViewChild('submitButton') submitButton;
    @ViewChild('submitButton') submitButton: ElementRef;

    constructor(
        private modalService: NgbModal,
        private contactService: ContactService,
        private renderer: Renderer2
    ) { }

    ngOnInit() {
        this.initForm();
    }

    ngAfterViewInit() {
        console.log(this.submitButton);
    }

    private getDismissReason(reason: any): string {
        if (reason === ModalDismissReasons.ESC) {
          return 'by pressing ESC';
        } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
          return 'by clicking on a backdrop';
        } else {
          return  `with: ${reason}`;
        }
    }

    private initForm() {
        const email = '';
        const message = '';

        this.contactForm = new FormGroup({
            email: new FormControl(null, Validators.email),
            message: new FormControl(null, Validators.required)
        });
    }

    onSubmit() {

        const email = this.contactForm.value.email;
        const message = this.contactForm.value.message;

        // at this point this.submitButton is UNDEFINED
        console.log(this.submitButton);

        //this.submitButton.nativeElement.style.backgroundColor = 'black';

        this.contactService.sendContactRequest(email, message, (submitSuccess: boolean) => {
            if (submitSuccess) {

                console.log('SUCCESS UPDATE UI');
                this.contactForm.value.email = '';
                this.contactForm.value.message = '';

            } else {
                console.log('ERROR update UI');
            }
        });
    }

    open(content) {
        console.log('in open func');
        this.modalService.open(content, {ariaLabelledBy: 'modal-basic-title'})
        .result
        .then(
            (result) => {
                console.log(`Closed with: ${result}`);
            },
            (reason) => {
                console.log(`Dismissed ${this.getDismissReason(reason)}`);
            }
        );
    }
}

这是我的完整模板:

<a
    class="nav-link"
    (click)="open(content)"
><i class="fas fa-envelope"></i></a>

<ng-template #content let-c="close" let-d="dismiss">

    <div class="modal-header">
        <h4 class="modal-title" id="modal-basic-title">Contact Us</h4>
        <button type="button" class="close" aria-label="Close" (click)="c()">
          <i class="fas fa-times"></i>
        </button>
    </div>

    <div class="modal-body">

        <form [formGroup]="contactForm" (ngSubmit)="onSubmit()">

            <div class="row justify-content-center">

                <div class="col-md-12 col-sm-12">
                    <div class="form-group">
                        <label for="email">Email</label>
                        <input
                            type="text"
                            class="form-control"
                            id="email"
                            formControlName="email"
                        >
                    </div>
                </div>

            </div>

            <div class="row justify-content-center">

                <div class="col-md-12 col-sm-12">
                    <div class="form-group">
                        <label for="message">Message</label>
                        <textarea
                            type="text"
                            class="form-control"
                            id="message"
                            formControlName="message"
                            rows="6"
                        ></textarea>
                    </div>
                </div>

            </div>

            <div class="row justify-content-center">

                <div class="col-md-12 col-sm-12">
                    <button #submitButton
                        id="submitButton"
                        class="btn btn-success w-100"
                        [disabled]="!contactForm.valid"
                    >Send</button>
                </div>

            </div>

            <div class="row">
                <div class="col-md-12 col-sm-12">
                    <div *ngIf="sentMessage" class="alert alert-success" role="alert">
                        {{ sentMessage }}
                    </div>
                </div>
            </div>

        </form>

    </div>

</ng-template>

任何帮助是极大的赞赏。

标签: javascriptangulartypescriptfrontendng-bootstrap

解决方案


我想要做的是,当用户单击“发送”按钮(请参阅下面的模板代码)时,该按钮将被禁用并说“发送...”。换句话说,我正在尝试操作属性视图模式组件。

//this.submitButton.nativeElement.style.backgroundColor = 'black';

如果我正确理解了这个问题(和你的代码),你基本上想做三件事:

  1. 单击发送后将按钮设置为禁用
  2. 将按钮文本设置为“正在发送...”
  3. 将按钮背景颜色设置为黑色(在您的代码中)

您可以通过数据绑定(数据绑定类型)来完成前两个。对于第三个,我找到了一种解决方法,让它工作(使用 dom,而不是 angular @Viewchild)。

  1. 您可以在打字稿文件中使用布尔变量(例如,“isDataSent: boolean”),或者在 HTML 中使用“!isValid”
  2. 您使用变量指定 .ts 文件中显示的文本并使用数据绑定来显示它
  3. 您通过 id 访问 dom 元素,设置颜色并删除 ''@ViewChild('submitButton') submitButton: ElementRef;'' 行。如果你想通过访问 dom 来做所有的事情,你也可以这样做:-)

这是示例代码(省略的行可以视为未触及,注释带有 )

将 HTML 按钮更改为:

          <button
              id="submitButton"
              class="btn btn-success w-100"
              [disabled]="!contactForm.valid || isDataSent"
          >{{submitButtonText}}</button>

所以在打字稿文件中:

export class ContactModalComponent implements OnInit, AfterViewInit {
  // ... code ...
  isDataSent: boolean;
  submitButtonText: string;
  // ... code ...
  ngOnInit() {
    //... code ...
    this.isDataSent = false;
    this.submitButtonText = 'Send';
    //... code ...
  }
  // ... code ...
  onSubmit() {
    const email = this.contactForm.value.email;
    const message = this.contactForm.value.message;

    const submitButton = document.getElementById('submitButton');
    if (submitButton) {
      submitButton.style.backgroundColor = 'black';
    } 
    this.submitButtonText = 'sending...';
    this.isDataSent = true;
    
    this.contactService.sendContactRequest(email, message, (submitSuccess: boolean) => {
        if (submitSuccess) {

            console.log('SUCCESS UPDATE UI');
            this.contactForm.value.email = '';
            this.contactForm.value.message = '';

        } else {
            console.log('ERROR update UI');
        }
    });
  }
  //... code ...
}

我正在使用 Angular CLI:11.2.8 和节点:14.16.0。
希望这会有所帮助,如果您对我的回答有任何改进,请告诉我。
-亚历克斯


推荐阅读