Digging Deeper
Overriding Core Methods
This page shows you how to override a core Wheels method — a model finder, a controller helper, or a view helper like linkTo() — while still being able to call the framework's original implementation from inside your override. You'll use the super-prefixed method convention, pick the right place for each kind of override, and see when a pass-through argument (like dataConfirm) makes an override unnecessary in the first place.
You'll learn:
- How the
super<name>convention works and why it replacedsuper.methodName() - How to override a model method and delegate with
superFindAll() - How to override a controller or view helper and delegate with
superLinkTo() - Where each override lives: a single controller,
app/controllers/Controller.cfc, orapp/views/helpers.cfm - When to skip the override entirely — the
data-*pass-through pattern for confirm dialogs - Which 4.0.x versions support controller/view overrides, and the workaround for older builds
How the convention works
Section titled “How the convention works”Wheels assembles models and controllers by mixing framework methods into your components at startup. Because the framework's findAll(), linkTo(), and friends arrive as mixins rather than through CFML inheritance, super.findAll() does not reach them — that syntax stopped working in Wheels 3.0.
Instead, when your component defines a method whose name collides with a framework mixin, Wheels keeps your version and registers the framework original under the same name prefixed with super. Override findAll() and the original becomes superFindAll(); override linkTo() and the original becomes superLinkTo(). Method names are case-insensitive, following normal CFML rules.
The alias is only created when you actually override something. A controller or model that overrides nothing gains no extra super* keys.
Overriding a model method
Section titled “Overriding a model method”Define the method in your model CFC. Delegate to the original with argumentCollection = arguments so every argument your caller passed flows through unchanged:
component extends="Model" {
function config() { }
public any function findAll() { // custom logic before calling the framework original return superFindAll(argumentCollection = arguments); }
}This works for any public framework method mixed into models — findOne(), columnNames(), save(), and so on.
Overriding a controller or view helper
Section titled “Overriding a controller or view helper”The same convention applies to everything mixed into controllers, which includes all view helpers (views execute in the controller's variables scope). Overriding linkTo() and delegating to the framework original looks like this:
component extends="Controller" {
function config() { }
public string function linkTo() { // example: give every generated link a default class if (!StructKeyExists(arguments, "class")) { arguments.class = "app-link"; } return superLinkTo(argumentCollection = arguments); }
}Every call to #linkTo(...)# in that controller's views now runs your version, and superLinkTo() hands off to the real framework helper — arguments, routing, and HTML escaping all behave exactly as stock.
Where the override lives
Section titled “Where the override lives”- One controller — define the override in that controller's CFC, as above.
- Every controller — define it in
app/controllers/Controller.cfc, the base controller your controllers extend. - View helpers, app-wide — define it in
app/views/helpers.cfm. That file is included into every controller before the framework mixins are integrated, so your version is already in place when the framework helper arrives — your version wins and the original is registered assuper<name>.
Version notes and the pre-fix workaround
Section titled “Version notes and the pre-fix workaround”Controller and view helper overrides gained super<name> delegation in the 4.0.x patch release that fixed #3325. Model overrides have supported it since 3.x.
Before you override: the data-* pass-through
Section titled “Before you override: the data-* pass-through”A common reason people reach for a linkTo() override is to add behavior like a JavaScript confirm dialog to generated links. You usually don't need an override for that: every HTML helper passes unknown arguments through as HTML attributes, and arguments starting with data are automatically hyphenized — dataConfirm becomes data-confirm, data_confirm works too.
<cfoutput> #linkTo( route = "editPost", key = post.id, text = "Edit", dataConfirm = "Discard your current draft and edit this post?" )#
#buttonTo( route = "post", key = post.id, text = "Delete", method = "delete", dataConfirm = "Delete this post permanently?" )#</cfoutput>Pair it with one delegated listener instead of per-link JavaScript:
document.addEventListener("click", function (e) { var el = e.target.closest("[data-confirm]"); if (el && !confirm(el.dataset.confirm)) { e.preventDefault(); e.stopImmediatePropagation(); }}, true);This replaces what plugins like jsconfirm did in older Wheels versions — no override, no plugin, and the attribute shows up on any helper that renders a tag.
Migrating from Wheels 2.5
Section titled “Migrating from Wheels 2.5”If you're upgrading an application from Wheels 2.5 that overrode core methods:
- Search for usages of
super.methodName() - Replace them with
superMethodName()— for example,super.findAll()becomessuperFindAll() - Test the overridden behavior to make sure results match
No changes are required for applications that don't override core methods.