Skip to content

Issue 84 Asset Deep Link Selected Nothing

Ed Mozley edited this page Aug 25, 2026 · 1 revision

Opening an asset from the asset table showed nothing (issue #84)

Clicking a row on the asset table took you to the split-pane asset screen, with the right asset id in the address bar β€” and then sat there with nothing selected and an empty details panel. The asset appeared only if you found it in the list and clicked it a second time.

Reported in issue #84 by dschipfel, who called it correctly: "This appears to be an initialization issue… users may assume the asset failed to load."

Fixed in 681cda74, released as update #1198.


1. What you saw

Asset Management β†’ table view, click any row.

You arrive at asset-management/index.php?asset=2. The page loads. The asset list on the left loads. The panel on the right, where the asset should be, is empty. Nothing is highlighted.

The id is right there in the URL, which is what makes it read as broken rather than as a mis-click. And clicking the same asset in the list works perfectly β€” so the asset is fine, the panel is fine, and only the arrival is wrong.


2. The mechanism

Two screens had drifted onto different spellings of the same thing.

The asset screen reads the id like this:

// asset-management/index.php β€” before
var aid = new URLSearchParams(window.location.search).get('asset_id');
if (aid) { … selectAsset(n); }

The table view wrote it like this:

// assets/js/asset-table.js β€” before
onRowClick: row => { window.location.href = `index.php?asset=${row.id}`; },

asset is not asset_id. get('asset_id') returned null, the if never ran, and nothing was ever selected.

Why it produced silence rather than an error

An unrecognised query parameter is not an error. Nothing validates it, nothing warns about it, and the browser is perfectly happy to carry it. So the page did exactly what it was told: it opened the asset module and selected nothing.

That is the whole reason this reads as a fault in the asset rather than a fault in the link. A broken link normally announces itself with a 404. This one delivered you to the right module, on the right page, with the right id visible in the address bar, and then quietly did nothing with it.

asset_id is not an arbitrary choice between two equals

FreeITSM already has a single declared answer for "what is the address of an asset":

// includes/entity_links.php
case 'asset':
    return 'asset-management/?asset_id=' . $id;

And the ticket inbox already links that way:

// assets/js/inbox.js
href="../asset-management/index.php?asset_id=${link.asset_id}"

So of the three places in the codebase that address an asset, two agreed and one did not. asset-table.js was the outlier, not a second valid convention.

This is the failure mode from issue #91

Issue #91 was the same shape: several places writing record addresses, disagreeing, and the disagreement showing up as a page that opens and does nothing. The lesson recorded then was that tolerance hides drift β€” the modules that accepted anything never surfaced the problem, and the two strict ones were where the dead links finally appeared.

The asset screen was one of the strict ones. It is strict because being strict is what made this findable.


3. The fix

Three changes, and only the first is the bug.

1. The table now writes the canonical spelling.

// assets/js/asset-table.js β€” after
onRowClick: row => { window.location.href = `index.php?asset_id=${row.id}`; },

2. The old spelling is still accepted β€” but not silently.

The table sent ?asset= until this fix, so those URLs are already in people's history and bookmarks. Refusing them would turn one bug into another.

var params = new URLSearchParams(window.location.search);
var aid = params.get('asset_id') || params.get('asset');

The important part is what happens next, in change 3: the address bar is rewritten to the canonical form. An old link works once and then corrects itself. That is deliberately different from being quietly tolerant, which is how the two spellings drifted apart in the first place.

3. The address bar now follows what you are looking at.

// asset-management/index.php β€” in selectAsset()
try {
    if (window.history && window.history.replaceState) {
        window.history.replaceState({ assetId: Number(assetId) }, '',
            window.location.pathname + '?asset_id=' + Number(assetId));
    }
} catch (e) { /* not fatal */ }

Click an asset in the list and the URL becomes that asset's URL β€” so it can be copied to a colleague, bookmarked, or reloaded and land back where you were.

Why replaceState and not pushState. The list stays on screen the whole time, so choosing an asset is not navigation. Pushing would fill the Back button with entries that never visibly go anywhere β€” press Back five times and the page appears not to move while the URL ticks backwards. The same shape already exists in the portal's ticket list (self-service/tickets.php), which uses replaceState for the same reason.

Why the try. History writes throw in some contexts β€” file:// origins, strict embedders. A URL nicety must never be the thing that stops an asset loading. Copied from the note already in self-service/tickets.php.


4. πŸ“ The files involved

File What changed
assets/js/asset-table.js Row click writes ?asset_id=. The bug.
asset-management/index.php Accepts the legacy ?asset=; selectAsset() writes the open asset into the address bar.
asset-management/table.php Cache-buster asset-table.js?v=6.

πŸ—„οΈ Already correct

File
includes/entity_links.php Declared asset_id all along. It was right; the table did not consult it.
assets/js/inbox.js Already linked with asset_id.

5. How it was verified

The real pages were driven in a headless browser.

Reproduced first. Before any change, ?asset=11 left no row selected while ?asset_id=11 selected one β€” the two spellings side by side, one working and one not.

After the fix, four checks:

?asset=11 (legacy) details shown, and the URL self-corrects to ?asset_id=11
?asset_id=12 (canonical) details shown
no parameter, then select an asset URL becomes ?asset_id=13
table.php serves the updated script

6. What this means for you

Clicking a row on the asset table now opens that asset properly, first time.

Any links you already made with the old address still work, and quietly become proper ones. And the asset screen's URL now tracks whichever asset you have open, so it is worth copying out of the address bar when you want to send somebody straight to a machine.


Related pages

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally