解决angular项目在IE10、IE11上运行,表单组件在输入之前就校验的问题

  • 问题描述
    在IE10和IE11中,表单中还没有输入任何内容,校验信息就显示出来了。
  • 现象举例
    在这里插入图片描述
  • 问题原因及解决办法
    这个问题在GitHub上已经讨论的很火了,原因也说的很明白了,并且angular团队也给出了解决办法。相关链接: issue-14440。终极解决办法:UniqueInputEventPlugin
  • 还是给个代码吧,所有相关信息包括用法都在注释里边
/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */

/**
 * https://github.com/angular/angular/issues/14440
 */

import { DOCUMENT } from '@angular/common';
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
import { ɵangular_packages_platform_browser_platform_browser_d as EventManagerPlugin } from '@angular/platform-browser';

/**
 * The injection token for enabling unique input event plugin.
 *
 * @publicApi
 */
export const UNIQUE_INPUT_EVENT_PLUGIN_CONFIG = new InjectionToken<UniqueInputEventPluginConfig>(
  'UniqueInputEventPluginConfig',
);

/**
 * @publicApi
 */
export interface UniqueInputEventPluginConfig {
  /**
   * Function that determines that plugin should be applied to element
   * Default is HTMLInputElement or HTMLTextAreaElement
   */
  shouldApplyToElement?(element: Element): boolean;
  /**
   * Function that determines that event is not require check for uniqueness
   * By default, all non user agent events is trusted
   */
  shouldTrustEvent?(event: Event): boolean;
}

const DEFAULT_UNIQUE_INPUT_EVENT_PLUGIN_CONFIG: UniqueInputEventPluginConfig = {
  shouldApplyToElement: (element: HTMLElement) => {
    return element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement;
  },
  /** Trust all non user agent events */
  shouldTrustEvent: (event: Event) => !event.isTrusted,
};

/**
 * @description
 *
 * This plugin checks if value of element is changed before firing input event
 *
 * Internet Explorer 10+ implements 'input' event but it erroneously fires under various situations,
 * e.g. when placeholder changes, when non english placeholder is used or a control is focused.
 * Fixed only from Edge 15.15002
 * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/101220
 * Will not be fixed in Internet Explorer
 * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11405058/
 *
 * @usageNotes
 * ### Example
 *
 * ```
 * @NgModule({
 *   providers: [{
 *      provide: EVENT_MANAGER_PLUGINS, multi: true,
 *      useClass: UniqueInputEventPlugin, deps: [DOCUMENT],
 *   }]
 * })
 * class MyModule {}
 * ```
 *
 * If there is a need to control when the plugin will be enabled (for example, IE 10+),
 * use `FactoryProvider` instead of `ClassProvider`
 *
 * @publicApi
 */
@Injectable()
export class UniqueInputEventPlugin extends EventManagerPlugin {
  private _config?: UniqueInputEventPluginConfig;

  constructor(
    @Inject(DOCUMENT) private _document: any,
    @Optional()
    @Inject(UNIQUE_INPUT_EVENT_PLUGIN_CONFIG)
    config?: UniqueInputEventPluginConfig,
  ) {
    super(_document);

    if (config) {
      this._config = { ...DEFAULT_UNIQUE_INPUT_EVENT_PLUGIN_CONFIG, ...config };
    } else {
      this._config = DEFAULT_UNIQUE_INPUT_EVENT_PLUGIN_CONFIG;
    }
  }

  supports(eventName: string): boolean {
    return !!this._config && eventName === 'input';
  }

  addEventListener(element: HTMLElement, eventName: string, originalHandler: (event: Event) => void): () => void {
    if (this._config && this._config.shouldApplyToElement && this._config.shouldApplyToElement(element)) {
      const targetElement = element as HTMLElement & { value?: any };

      let value = targetElement.value;

      /**
       * Keydown event type MUST be dispatched before the beforeinput, input,
       * and keyup events associated with the same key.
       * https://www.w3.org/TR/uievents/#keydown
       */
      const keydownHandler = () => {
        value = targetElement.value;
      };

      const inputHandler = (event: Event) => {
        /**
         * Event is trusted
         * OR element.value changed after listener added
         * OR element.value changed after input
         * OR element.value changed after keydown
         */
        if (
          (this._config && this._config.shouldTrustEvent && this._config.shouldTrustEvent(event)) ||
          targetElement.value !== value
        ) {
          value = targetElement.value;
          originalHandler(event);
        }
      };

      element.addEventListener('keydown', keydownHandler, false);
      element.addEventListener(eventName, inputHandler, false);
      return () => {
        element.removeEventListener(eventName, inputHandler, false);
        element.removeEventListener('keydown', keydownHandler, false);
      };
    }

    element.addEventListener(eventName, originalHandler, false);
    return () => element.removeEventListener(eventName, originalHandler, false);
  }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值