点击通话功能两次角

时间:2019-03-12 09:29:57

标签: angular typescript

我在我的应用程序中创建了一个通用按钮组件,该组件将从导入的父组件中执行特定功能。 在此特定示例中,我有一个登录表单,单击该按钮后将调用login()函数。

我似乎遇到的问题是,每次我单击登录按钮时,它都会两次执行该方法,而不是一次。我不确定为什么会这样。旁边有一个忘记密码的按钮,该按钮也来自同一模板,但应该具有不同的功能,因为我将不同的功能绑定到click指令,但是当我单击时该链接将再次运行login()函数,但这一次。

这是我的登录表单的屏幕快照,用于了解布局:

login form

这是我的代码:

button.component.ts

import { Component, ViewEncapsulation, Input, Output, OnInit, EventEmitter } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'app-button',
  templateUrl: './button.component.html',
  styleUrls: ['./button.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class ButtonComponent implements OnInit{

  @Input() group: FormGroup;
  @Input() type: string;
  @Input() description: string;
  @Input() class: string;
  @Output() callFunction = new EventEmitter();

  constructor(){ }

  ngOnInit(){
    this.group = new FormGroup({});
  }

  onClick(event){
    this.callFunction.emit(event);
  }

}

button.component.html

<div [formGroup]="group">
  <button [type]="type" [class]="class" (click)="onClick($event)">{{ description }}</button>
</div>

login.component.ts

import { Component, OnInit, ViewChild, ViewContainerRef, AfterContentInit, ComponentFactoryResolver } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { OauthService } from 'src/app/services/oauth/oauth.service';
import { LoggerService } from 'src/app/services/logger/logger.service';
import { ToastrService } from 'ngx-toastr';
import { TranslatePipe } from 'src/app/pipes/translate/translate.pipe';
import { TextFieldComponent } from 'src/app/components/core/text-field/text-field.component';
import { ButtonComponent } from 'src/app/components/core/button/button.component';

/**
* This component is rendered at the start of application, it provides the UI
* & functionality for the login page.
*/
@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})

/**
* This class is used to build a login form along with initialization of validators
* as well as authenticate the user, and reroute upon success
*/
export class LoginComponent implements OnInit, AfterContentInit{

  @ViewChild('username', { read: ViewContainerRef }) username;
  @ViewChild('password', { read: ViewContainerRef }) password;



  /**
  * This property initializes the formGroup element.
  */
  userForm: FormGroup;
  /**
  * The constructor initializes Router, FormBuilder, OauthService, LoggerService, ToastrService
  * & TranslatePipe in the component.
  */
  constructor(private router: Router,
    private fb: FormBuilder,
    private oauth: OauthService,
    private logger: LoggerService,
    private toastr: ToastrService,
    private translate: TranslatePipe,
    private resolver: ComponentFactoryResolver) { }
  /**
  * This is the hook called on the initialization of the component, it initializes
  * the form.
  */
  ngOnInit() {
    this.buildForm();
  }



  /**
   * This method initialized the the formGroup element. Its properties and the validators.
   *
   * @method buildForm
   * @return
   */
  buildForm() {
    this.userForm = this.fb.group({
      'username': ['', Validators.required],
      'password': ['', Validators.required],
    });
  }
  /**
   * This method returns the values of the form controls.
   *
   * @return
   */
  get form() { return this.userForm.controls; }
  /**
   * This method is triggered on success, it reroutes the user to main page.
   *
   * @return
   */
  onSuccess() {
    let result = this.translate.transform("pages[login_page][responses][success]");
    this.logger.info(result);
    this.toastr.success(result);
    this.router.navigate(['main']);
  }
  /**
   * This method is triggered when user clicks log-in, it calls the aunthenication method
   * from oauth service.
   *
   * @return
   */
  login() { console.log("i am called00");
    this.oauth.authenticateUser(this.form.username.value, this.form.password.value, this.onSuccess.bind(this));
  }

  ngAfterContentInit() {
    this.buildUserField();
    this.buildPasswordField();
  }




  /**
  * This function builds the username field, imports the TextFieldComponent
  *
  */
  buildUserField(){
    let data = {
      type: "text",
      class: "form-control",
      placeholder: this.translate.transform("pages[login_page][login_form][placeholders][username]"),
      id: "username",
      autoComplete: "username",
      formControlName: "username",
      group: this.userForm
      }
    const inputFactory = this.resolver.resolveComponentFactory(TextFieldComponent);
    const usernameField = this.username.createComponent(inputFactory);
    usernameField.instance.group = data.group;
    usernameField.instance.type = data.type;
    usernameField.instance.class = data.class;
    usernameField.instance.placeholder = data.placeholder;
    usernameField.instance.id = data.id;
    usernameField.instance.autoComplete = data.autoComplete;
    usernameField.instance.formControlName = data.formControlName;
  }

  /**
  * This function builds the password field, imports the TextFieldComponent
  *
  */
  buildPasswordField(){
    let data = {
      type: "password",
      class: "form-control",
      placeholder: this.translate.transform("pages[login_page][login_form][placeholders][password]"),
      id: "password",
      autoComplete: "password",
      formControlName: "password",
      group: this.userForm
      }
    const inputFactory = this.resolver.resolveComponentFactory(TextFieldComponent);
    const passwordField = this.password.createComponent(inputFactory);
    passwordField.instance.group = data.group;
    passwordField.instance.type = data.type;
    passwordField.instance.class = data.class;
    passwordField.instance.placeholder = data.placeholder;
    passwordField.instance.id = data.id;
    passwordField.instance.autoComplete = data.autoComplete;
    passwordField.instance.formControlName = data.formControlName;
  }


  /**
  * This function builds the login button functionality, imports the ButtonComponent
  *
  */
  buildLoginButton(){
    this.login();
  }


  /**
  * This function builds the forgot password link functionality, imports the ButtonComponent
  *
  */
  buildForgotPasswordButton(){
  }

  /**
  * This function builds the sign up button functionality, imports the ButtonComponent
  *
  */
  buildSignUpButton(){
  }



}

login.component.html

<div class="app-body">
  <main class="main d-flex align-items-center">
    <div class="container center">
      <div class="row">
        <div class="col-md-8 mx-auto">
          <div class="card-group">
            <div class="card p-4">
              <div class="card-body">
                <form [formGroup]="userForm" (submit)="login()">
                  <h1>{{ 'pages[login_page][login_form][labels][login]' | translate }}</h1>
                  <p class="text-muted">{{ 'pages[login_page][login_form][labels][sign_in]' | translate }}</p>
                  <div class="input-group mb-3">
                    <div class="input-group-prepend">
                      <span class="input-group-text"><i class="icon-user"></i></span>
                    </div>
                    <div #username> </div>
                  </div>
                  <div class="input-group mb-4">
                    <div class="input-group-prepend">
                      <span class="input-group-text"><i class="icon-lock"></i></span>
                    </div>
                    <div #password> </div>
                  </div>
                  <div class="row">
                    <div class="col-6">
                    <app-button description="{{ 'pages[login_page][login_form][buttons][login]' | translate }}" class="btn btn-primary px-4" (callFunction)="buildLoginButton()"></app-button>
                    <!--  <button type="button" class="btn btn-primary px-4" (click)="login()">{{ 'pages[login_page][login_form][buttons][login]' | translate }}</button> -->
                    </div>
                    <div class="col-6 text-right">
                      <app-button description="{{ 'pages[login_page][login_form][urls][forgot_password]' | translate }}" class="btn btn-link px-0" (callFunction)="buildForgotPasswordButton()"></app-button>
                    <!--  <button type="button" class="btn btn-link px-0">{{ 'pages[login_page][login_form][urls][forgot_password]' | translate }}</button>-->
                    </div>
                  </div>
                </form>
              </div>
            </div>
            <div class="card text-white bg-primary py-5 d-md-down-none" style="width:44%">
              <div class="card-body text-center">
                <div>
                  <h2>{{ 'pages[login_page][sign_up_panel][labels][sign_up]' | translate }}</h2>
                  <p>{{ 'pages[login_page][sign_up_panel][labels][new_account]' | translate }}</p>
                      <app-button description="{{ 'pages[login_page][sign_up_panel][buttons][register]' | translate }}" class="btn btn-primary active" (callFunction)="buildSignUpButton()"></app-button>
                <!--  <button type="button" class="btn btn-primary active mt-3">{{ 'pages[login_page][sign_up_panel][buttons][register]' | translate }}</button> -->
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </main>
</div>

侧注:(尽管从技术上讲,这不是问题标题的一部分),但我正在使用CoreUI设置表单的样式,该表单已导入到我的全局样式文件中,并且在我不使用时可以正常工作用于文本字段和按钮的可重用组件,但是现在当我开始使用那些子组件时,它们以某种方式不继承CoreUI样式,只是简单的引导程序,如果有人愿意,请帮我,我将非常感激:)

2 个答案:

答案 0 :(得分:3)

在您的表单中,您有login()

的提交回调

<form [formGroup]="userForm" (submit)="login()">

,并且您的提交按钮中有一个回调buildLoginButton,该回调电话正在调用login(),这是发生问题的原因。

这样做可以解决您的问题

<form [formGroup]="userForm">

答案 1 :(得分:1)

您的按钮的类型为“ text”。这不是有效值。 它应该是“ button|submit|reset”(请参见doc for "type" attribute

此处,默认情况下为“提交”,因此调用表单(login())的Submit回调。

您应将按钮的类型更改为button