programing

Angular 2 및 브라우저 자동 채우기

sourcetip 2023. 6. 22. 00:07
반응형

Angular 2 및 브라우저 자동 채우기

저는 Angular reactive 형태의 로그인 페이지를 구현하고 있습니다.양식이 올바르지 않으면 "로그인" 단추가 비활성화됩니다.

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
    selector: 'signin',
    templateUrl: './signin.component.html'
})
export class SignInComponent implements OnInit {
    private signInForm: FormGroup;

    constructor(private formBuilder: FormBuilder) { }

    ngOnInit() {
        this.buildForm();
    }

    private buildForm(): void {
        this.signInForm = this.formBuilder.group({
            userName: ['', [Validators.required, Validators.maxLength(50)]],
            password: ['', [Validators.required, Validators.maxLength(50)]]
        });

        this.signInForm.valueChanges
            .subscribe((data: any) => this.onValueChanged(data));

        this.onValueChanged();
    }

    private onValueChanged(data?: any) {
        console.log(data);
    }

그래서 브라우저에서 실행하면 "userName" 및 "passwords" 필드가 미리 채워집니다.그리고 콘솔에서 '{userName: "email@email.com ", 암호: " }', 결과적으로 "filename" 버튼이 비활성화되었습니다.그러나 페이지의 어딘가를 클릭하면 ValueChanged에서 트리거되'{userName: "email@email.com ", 암호: "123456" } 및 버튼 "filename"이 활성화됩니다.

제가 몰래 가면.필드가 미리 채워지지 않았지만 값을 입력(선택)하면 콘솔에 '{userName: "email@email.com ", 암호: "123456" }, 추가 클릭 없이 "filename" 버튼이 활성화됩니다.

그것들은 다른 이벤트일 수도 있습니까?자동 채우기 및 자동 완성?각도는 그들과 다르게 작용합니까?

그것을 해결하는 가장 좋은 방법은 무엇입니까?그리고 브라우저 자동 채우기 필드에서 onValueChanged 함수가 한 번만 실행되는 이유는 무엇입니까?

Chrome 브라우저의 문제: 사용자가 페이지를 클릭하기 전에 자동 입력 후 암호 필드의 값에 액세스할 수 없습니다.두 가지 방법이 있습니다.

  1. 암호 필드의 유효성 검사를 제거합니다.
  2. 암호 자동 완성을 비활성화합니다.

당신이 사용할 수 있다는 것을 알게 되었습니다.autocomplete="new-password"

여기에 설명된 바와 같이

이렇게 하면 암호 필드가 자동으로 채워지지 않습니다. 이것이 바로 저의 경우입니다.위의 링크에서 사용할 수 있는 다른 많은 자동 완성 특성이 있습니다.

이것은 나에게 효과가 있습니다.

before(자동 채우기)

<div class="form-group form-row required">
     <input class="input p-l-20 form-control" formControlName='otp' type="text" name="otp" placeholder="Enter OTP">
</div>

after(자동 충전이 안 됨, 정상 작동)

<div class="form-group form-row required">
       <input class="input p-l-20 form-control" formControlName='otp' type="text" name="otp" placeholder="Enter OTP">
       <!-- this dummy input is solved my problem -->
       <input class="hide"  type="text">
</div>

참고 숨기기는 부트스트랩 v4 클래스입니다.

Chrome v58.0.3029.96에서도 같은 문제에 직면했습니다.다음은 유효성 검사 및 자동 완성을 유지하기 위한 해결 방법입니다.

export class SigninComponent extends UIComponentBase
{
    //--------------------------------------------------------------------------------------------
    // CONSTRUCTOR
    //--------------------------------------------------------------------------------------------
    constructor(viewModel: SigninViewModel)
    {
        super(viewModel);

        // Autofill password Chrome bug workaround
        if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1)
        {
            this._autofillChrome = true;
            this.vm.FormGroup.valueChanges.subscribe(
                (data) =>
                {
                    if (this._autofillChrome && data.uname)
                    {
                        this._password = " ";
                        this._autofillChrome = false;
                    }
                });
        }
    }

    //--------------------------------------------------------------------------------------------
    // PROPERTIES
    //--------------------------------------------------------------------------------------------
    private _password: string;
    private _autofillChrome: boolean;

    //--------------------------------------------------------------------------------------------
    // COMMAND HANDLERS
    //--------------------------------------------------------------------------------------------
    private onFocusInput()
    {
        this._autofillChrome = false;
    }
}

그리고 내 html에는:

<input mdInput 
       [placeholder]="'USERNAME_LABEL' | translate" 
       [formControl]="vm.FormGroup.controls['uname']" 
       (focus)="onFocusInput()" />
[...]
<input mdInput 
       type="password" 
       [placeholder]="'PASSWORD_LABEL' | translate" 
       [formControl]="vm.FormGroup.controls['password']" 
       (focus)="onFocusInput()"
       [(ngModel)]="_password" />

도움이 되길 바랍니다.

참고:vm에 정의되어 있습니다.UIComponentBase뷰 모델을 참조합니다.SigninViewModel내 구성 요소의.FormGroup인스턴스는 비즈니스 로직이 애플리케이션의 뷰와 엄격하게 분리되므로 뷰 모델에 정의됩니다.

갱신하다

v59부터 필드 자동 완료 시 입력의 포커스 이벤트가 발생하는 것 같습니다.따라서 위의 해결 방법은 더 이상 작동하지 않습니다.다음은 시간 초과를 사용하여 필드가 자동 완료 또는 사용자에 의해 업데이트되는지 여부를 확인하는 업데이트된 해결 방법입니다.

export class SigninComponent extends UIComponentBase
{
    //--------------------------------------------------------------------------------------------
    // CONSTRUCTOR
    //--------------------------------------------------------------------------------------------
    constructor(viewModel: SigninViewModel)
    {
        super(viewModel);

        // Autofill password Chrome bug workaround
        if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1)
        {
            this._autofillChrome = true;
            setTimeout(
                () =>
                {
                    this._autofillChrome = false;
                },
                250 // 1/4 sec
            );
            this.vm.FormGroup.valueChanges.subscribe(
                (data) =>
                {
                    if (this._autofillChrome && data.uname)
                    {
                        this._password = " ";
                        this._autofillChrome = false;
                    }
                });
        }
    }

    //--------------------------------------------------------------------------------------------
    // PROPERTIES
    //--------------------------------------------------------------------------------------------
    private _password: string;
    private _autofillChrome: boolean;
}

그리고 내 html에는:

<input mdInput 
       [placeholder]="'USERNAME_LABEL' | translate" 
       [formControl]="vm.FormGroup.controls['uname']" />
[...]
<input mdInput 
       type="password" 
       [placeholder]="'PASSWORD_LABEL' | translate" 
       [formControl]="vm.FormGroup.controls['password']" 
       [(ngModel)]="_password" />

해결 방법을 찾았습니다.

  1. 일부 varisDisabled 생성: 부울 = false UPDATE: 1.1 하나 더 - var initCount: number = 0;

    ngOnInit(): void { this.isDisabled = false; this.initCount++; }

  2. 메서드 만들기

코드는 다음과 같습니다.

// This method will be called async
onStart(): Observable<boolean> {
    if (this.loginFomrControl.hasError('required') && 
    this.passwordFormControl.hasError('required') && this.initCount == 1) {
      this.isDisabled = false;

      // increase init count so this method wound be called async
      this.initCount++;
    }

    return new BehaviorSubject<boolean>(true).asObservable();
  }

// This method will ve called on change
validateForm() {
    if (this.loginFormControl.value != '' && this.passwordFormControl.value != '') {
      this.isDisabled = false;
    } else if (this.loginFomrControl.value == '' || this.passwordFormControl.value == '') {
      this.isDisabled = true;
    }
  }
  1. 다음과 같은 방법으로 html을 업데이트합니다.

여기 HTML의 샘플이 있습니다.

<div class="container" *ngIf="onStart() | async">
<!-- Do Stuff -->
  <mat-form-field class="login-full-width">
    <input matInput placeholder="{{ 'login_email' | translate }}" id="login_email" [formControl]="loginFomrControl" (change)="validateForm()">
    <mat-error *ngIf="loginFomrControl.hasError('email') && !loginFomrControl.hasError('required')">
            {{'login_email_error' | translate}}
    </mat-error>
    <mat-error *ngIf="loginFomrControl.hasError('required')">
            {{ 'login_email' | translate }}
        <strong>{{ 'login_required' | translate }}</strong>
    </mat-error>
  </mat-form-field>
<!-- Do Stuff -->
</div>

완전성을 위해:응답하지 않는 로그인 양식이 있습니다.

<form name="loginForm" role="form" (ngSubmit)="onLoginSubmit()">
  <input name="username" #usernameInp>
  <input type="password" name="password" #passwordInp>
  <button type="submit">Login</button>
</form>

사용할 경우[(ngModel)]="username"변수username브라우저 자동 채우기 기능이 시작되면 관련 구성 요소가 채워지지 않습니다.

따라서 대신 ViewChild로 작업합니다.

@ViewChild('usernameInp') usernameInp: ElementRef;
@ViewChild('passwordInp') passwordInp: ElementRef;
...
onLoginSubmit() {
  const username = this.usernameInp.nativeElement.value;
  const password = this.passwordInp.nativeElement.value;
  ...

이렇게 하면 사용자가 로그인을 클릭하면 브라우저에서 제공하는 값에 액세스할 수 있습니다.

나의 솔루션 2019 버전:기스트 허브

// <ion-input (change)="fixAutoFill($event, 'password')" #passwordInput autocomplete="off" formControlName="password" type="password"></ion-input>
// <ion-input (change)="fixAutoFill($event, 'username')" #usernameInput autocomplete="off" type="text" formControlName="username"></ion-input>


  fixAutoFill(event, type) {
    const value = event.target.value;
    if (type === 'username') {
      this.loginForm.patchValue({
        username: value
      }, {emitEvent: true, onlySelf: false});
    } else {
      this.loginForm.patchValue({
        password: value
      }, {emitEvent: true, onlySelf: false});
    }
    // console.log('after click', this.loginForm.value);
  }

  @ViewChild('usernameInput') usernameInput: IonInput;
  @ViewChild('passwordInput') passwordInput: IonInput;

http://webagility.com/posts/the-ultimate-list-of-hacks-for-chromes-forced-yellow-background-on-autocompleted-inputs

이거 한번 해보세요.잠시 머리를 쥐어짜긴 했지만 이것이 효과가 있었습니다.

input:-webkit-autofill {
  -webkit-transition-delay: 99999s;
}

속성을 추가하여 이 문제를 해결했습니다.autocomplete="new-feildName"태그를 입력합니다.

예:

<input type="text" class="mr-input" formControlName="email" 
placeholder="Adresse e-mail" autocomplete="new-email"/>

참고: 모든 필드에 자동 완성을 추가해야 합니다.

나는 기능을 만들었습니다.

formIsValid(): boolean{ return this.form.valid; }

단추에 추가하는 것보다 더 중요합니다.

<button [disabled]="!formIsValid()" type="submit">LogIn</button>

저한테는 효과가 있어요.

언급URL : https://stackoverflow.com/questions/41932810/angular-2-and-browser-autofill

반응형