如何强制事件处理程序优先?

问题描述 投票:0回答:1

我有 JavaScript 代码,其中我更改了

invalid
事件上的输入字段 css 类,以将
error
类添加到具有
div
类的父级
form-row

此外,我还在输入的表单字段上附加一个事件侦听器,并在用户与表单字段(文本、文本区域、下拉选择框等)交互后单击以删除错误类

现在,这些表单字段已经附加了事件处理程序,并且有些字段停止了事件传播。

某些元素不会调用

formElementRow.classList.remove('error');
,因为某些其他事件处理程序首先起作用。

是否有一种快速方法可以强制我在此处定义的事件处理程序优先,同时仍允许其他事件处理程序在页面上执行操作?

我控制表单的 html,我不想用注册其他事件处理程序的代码更改任何内容。

这是我的代码,适用于除停止事件传播的元素之外的所有表单元素:

const formErrorStatesOnBrowserSideValidation = () => {
    const targetClass = '.form-row';
    document.addEventListener('invalid', (invalidEvent) => {
        const {target} = invalidEvent;
        const formElementRow = target.closest(targetClass);

        if (formElementRow) {
            formElementRow.classList.add('error');
        }

        ['input', 'click'].forEach(event => {
            // some elements have other js / jQuery applied to them that stops event propagation hence the class removal is never called to those
            target.addEventListener(event, () => {
                formElementRow.classList.remove('error');
            });
        });
    }, true);
};
formErrorStatesOnBrowserSideValidation();

这是来自以下问题的后续问题:当用户单击 html5 无效表单中的提交按钮时要监听什么事件?

javascript dom-events stoppropagation event-propagation
1个回答
0
投票

OP 必须在所有受影响的表单控件的最方便的父级别处理每个表单控件的无效事件/状态,最好是表单元素本身,而不一定在

document
级别。

在这样的父级别,OP 无法控制的任何事件处理程序是否阻止

invalid
事件类型的传播并不重要;相反,OP 可以阻止
invalid
事件到达每个订阅的表单控件的目标处理程序。

function handleInvalidControl (evt) {

  // - none of the below three lines does interfer with the event
  //   handling of any other invalid form-control because each
  //   invalid control dispatches its invalid event separately.
  //
  evt.cancleBubble = true;
  evt.stopPropagation();
  evt.stopImmediatePropagation();
  
  console.log('control ...', {
    target: evt.target,
    currentTarget: evt.currentTarget,
  });
}
document
  .querySelectorAll('[type="text"]')
  .forEach(control =>
    control.addEventListener('invalid', handleInvalidControl, true)
  );

document
  .forms[0]
  .addEventListener('invalid', evt => {

    // - if invoked, it will stop the propagation
    //   towards any effected form-control
    //
    // evt.stopPropagation();

    console.log('form ...', {
      target: evt.target,
      currentTarget: evt.currentTarget,
    });

  }, true);

document
  .forms[0]
  .addEventListener('submit', evt => {

    evt.preventDefault();
    evt.currentTarget.reset();
  });
body { margin: 0; }
form { width: 44%; }
label { display: block; margin: 8px 0; }
.as-console-wrapper { left: auto!important; top: 8px; width: 56%; min-height: 100%; }
<form>
  <fieldset>
    <legend>validation test</legend>
    <label>
      <span>No digits</span>
      <input type="text" pattern="\D+" required />
    </label>
    <label>
      <span>No word characters</span>
      <input type="text" pattern="[\W+]+" required />
    </label>
  </fieldset>
  <button type="submit">Submit</button>
</form>

© www.soinside.com 2019 - 2024. All rights reserved.