How to regenerate fullslug after moving nodes in a NestedTree?

Hi! My model uses the SluggableTree and NestedTree traits. When I manually reorder records in the backend list view using drag & drop, the fullslug field is not regenerated. How can I force fullslug to be rebuilt after changing a node’s position in the tree?

Hi Radek,

The SluggableTree trait provides a public fullSlugAttributes() method that rebuilds the fullslug for a node and all its descendants, but nothing calls it automatically after a reorder. You need to wire it up yourself, the same way Tailor does internally.

In your backend controller (the one with ListController), add a listAfterReorder method:

public function listAfterReorder($record, $definition = null)
{
    // Reload to get the new tree position
    $record = $record->newQueryWithoutScopes()->find($record->getKey());

    // Rebuilds fullslug on this node and all descendants
    $record->fullSlugAttributes();
}

The reload step matters because the in-memory $record still has its pre-move parent_id and nesting values when the callback fires.

If you also want this to happen for programmatic moves outside the backend list (not just drag & drop), bind to model.afterSave in your model and call $this->fullSlugAttributes() when parent_id is dirty.

For reference, this is exactly what Tailor’s Entries controller does, delegating to its RecordIndexer class which walks the tree and saves only the records whose fullslug actually changed.

Hope that helps!

1 Like

The listAfterReorder function is exactly what I was looking for. Thank you, @daftspunk!

How to handle fullslug translation using Rainlab Translate?

For translating the fullslug, I’d recommend using October\Rain\Database\Traits\Translatable (the core trait)

Add slug and fullslug to your model’s $translatable array and it will handle the per-locale storage transparently alongside SluggableTree.

Just to clarify: if I use this core trait and add both slug and fullslug to $translatable, will the translated fullslug be generated automatically from the translated base slug? Or do I still need to implement that logic myself? I’d prefer not to translate fullslug manually.

Yes that should be correct.