{"record":{"id":"b2be01c3fe1beab7","repo":"oxc-project/oxc","slug":"prefer-addeventlistener-over-their-on-functi","errorCode":null,"errorMessage":"Prefer `addEventListener()` over their `on`-function counterparts.","messagePattern":"Prefer `addEventListener\\(\\)` over their `on`-function counterparts\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/unicorn/prefer_add_event_listener.rs","lineNumber":9,"sourceCode":"use oxc_ast::AstKind;\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::Span;\n\nuse crate::{AstNode, context::LintContext, rule::Rule};\n\nfn prefer_add_event_listener_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Prefer `addEventListener()` over their `on`-function counterparts.\")\n        .with_help(\n            \"`addEventListener()` can register multiple handlers and accepts options such as `{ once: true }`; assigning to `on<event>` replaces any previously registered handler.\",\n        )\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct PreferAddEventListener;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Enforces the use of `.addEventListener()` and `.removeEventListener()` over their `on`-function counterparts.\n    ///\n    /// For example, `foo.addEventListener('click', handler);` is preferred over `foo.onclick = handler;` for HTML DOM Events.\n    ///\n    /// ### Why is this bad?\n    ///","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/unicorn/prefer_add_event_listener.rs#L1-L27","documentation":"Lint diagnostic from oxlint's `unicorn/prefer-add-event-listener` rule. Assigning to `on<event>` properties (`el.onclick = ...`) silently replaces any previously registered handler and cannot use options like `{ once: true }`. The rule requires `addEventListener()` so multiple handlers can coexist and options are available.","triggerScenarios":"Any assignment to an `on`-prefixed DOM event handler property found in the AST: `button.onclick = handleClick;`, `window.onload = init;`, `document.body.onkeydown = onKey;` (also `on(` setter forms like jQuery-style `$(el).on(...)` variants the rule recognizes). Fires during oxlint runs when the rule is enabled.","commonSituations":"Legacy tutorial code using `window.onload`, HTML attributes ported to JS (`onclick=`), or refactors that add a second listener and accidentally clobber the first because `onX =` overwrites. Common when a codebase adopts oxlint's unicorn category and old page scripts get flagged in bulk.","solutions":["Replace the assignment with `el.addEventListener('click', handler)` (and `removeEventListener` where you previously set `onX = null`).","Use options when useful: `el.addEventListener('click', handler, { once: true })`.","If the overwrite behavior is intentional (guaranteeing a single handler), keep the assignment but suppress with `// oxlint-disable-next-line unicorn/prefer-add-event-listener` and leave a comment why.","Disable the rule in `.oxlintrc.json` for DOM-light codebases where it adds noise."],"exampleFix":"// before\nbutton.onclick = () => submit();\n\n// after\nbutton.addEventListener('click', () => submit());","handlingStrategy":"validation","validationCode":"// oxlint --filter unicorn/prefer-add-event-listener src/\n// CI gate: oxlint --deny-warnings src/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to addEventListener/removeEventListener; treat `onX =` as legacy API only.","Where a single guaranteed handler is required, document it next to an inline suppression comment.","Codemod old pages once: search `\\.on[a-z]+\\s*=` and convert."],"tags":["oxlint","unicorn","dom","events","best-practice"],"backgroundTag":"lint-rule-violation","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}