{"record":{"id":"d493f09f17bcdcbf","repo":"oxc-project/oxc","slug":"model-definition-is-deprecated","errorCode":null,"errorMessage":"`model` definition is deprecated.","messagePattern":"`model` definition is deprecated\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/vue/no_deprecated_model_definition.rs","lineNumber":21,"sourceCode":"use serde::{Deserialize, Serialize};\n\nuse oxc_ast::{\n    AstKind,\n    ast::{Expression, ObjectExpression, ObjectPropertyKind},\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::Span;\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    rule::{DefaultRuleConfig, Rule},\n    utils::is_vue_component_options_object,\n};\n\nfn deprecated_model_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"`model` definition is deprecated.\").with_label(span)\n}\n\nfn vue3_compat_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\n        \"`model` definition is deprecated. You may use the Vue 3-compatible `modelValue`/`update:modelValue` though.\",\n    )\n    .with_label(span)\n}\n\n#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\nstruct NoDeprecatedModelDefinitionConfig {\n    /// Allow `model: { prop: 'modelValue', event: 'update:modelValue' }` (or\n    /// the kebab-case `model-value` variant) which is forwards-compatible with\n    /// Vue 3's `v-model`.\n    allow_vue3_compat: bool,\n}\n","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/vue/no_deprecated_model_definition.rs#L3-L39","documentation":"Diagnostic from oxlint's vue/no-deprecated-model-definition rule (since oxlint 1.63.0). It fires on the Vue 2 `model` option used to customize v-model (e.g. model: { prop: 'checked', event: 'change' }). Vue 3 replaced it with the standard modelValue prop and update:modelValue event, and ignores the old option — the binding silently stops working. The rule's allowVue3Compat option (allow_vue3_compat) permits the exact forwards-compatible shape and routes anything else to this base diagnostic.","triggerScenarios":"A Vue component options object (is_vue_component_options_object) declares a `model` property, and either allowVue3Compat is false or the option's prop/event pair is not exactly modelValue/update:modelValue (or the kebab model-value variant).","commonSituations":"Form/input wrapper components migrated from Vue 2 that customized v-model's prop name; after upgrade the component accepts `checked` in code but templates using v-model bind to modelValue, causing undefined values with no error.","solutions":["Rename the prop to modelValue and emit update:modelValue: this.$emit('update:modelValue', val)","If the component already targets the compat shape, verify prop: 'modelValue', event: 'update:modelValue' exactly and set allowVue3Compat: true","For named v-models (v-model:title), use the update:title event convention"],"exampleFix":"// before\nmodel: {\n  prop: 'checked',\n  event: 'change',\n},\nprops: ['checked'],\n// after\nprops: ['modelValue'],\nemits: ['update:modelValue'],\nmethods: {\n  onInput(e) { this.$emit('update:modelValue', e.target.value) },\n}","handlingStrategy":"validation","validationCode":"# find custom v-model options\ngrep -rnE \"^\\s*model: *\\{\" --include='*.vue' src","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Author v-model components with modelValue + update:modelValue from day one on Vue 3","If you keep the model option transitionally, set allowVue3Compat and match the exact compat shape"],"tags":["vue","oxlint","lint","v-model","vue3","migration","deprecated"],"backgroundTag":"vue-2-to-3-migration","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"}