Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Richlist Widget Laravel Package

friendsofvictoire/richlist-widget

A Laravel package that adds a configurable rich-list widget for dashboards and admin panels. Render compact lists of records or metrics with labels, values, icons, and links, making key information easy to scan at a glance.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: it is not a Laravel package. friendsofvictoire/richlist-widget is a Symfony bundle for Victoire DCMS, a Symfony CMF-based CMS. There is no service provider, no config/richlist.php, no php artisan vendor:publish. The last release was August 2016, it has zero stars and zero dependents, and it is effectively abandoned. If you are starting a Laravel app today, you will not install this — you will reimplement the concept (a repeatable list of rich content blocks) with Eloquent, a Blade component, and a repeater field in your admin panel. The steps below apply only if you inherited a legacy Victoire/Symfony app.

Minimal install (legacy Victoire app):

composer require friendsofvictoire/richlist-widget

Register the bundle in app/AppKernel.php (or config/bundles.php on Symfony 4-era forks):

new Victoire\Widget\RichListBundle\VictoireWidgetRichListBundle(),

Declare the widget class so Victoire's widget palette knows about it:

# app/config/config.yml
victoire_core:
    widgets:
        richlist:
            class: Victoire\Widget\RichListBundle\Entity\WidgetRichList

Where to look first, in this order:

  1. Entity/WidgetRichList.php — the widget model, getWidgetName(), and the relation to its items.
  2. Form/WidgetRichListType.php — how items are collected in the backend editor (look for the collection type and allow_add).
  3. Resources/views/Widget/show.html.twig — the front-end render; this is what you will override 90% of the time.
  4. Resources/config/doctrine/*.orm.xml — tells you whether items are a Doctrine collection or a serialized array.

First use case: drop a "Rich list" widget into a page template slot in the Victoire backend, add 3–5 items (title, rich text, link, optional image), save, and confirm the front end renders. That is the entire day-to-day loop.

Implementation Patterns

Widget definition. A Victoire widget is a Doctrine entity extending BaseWidget with a short getWidgetName(). The rich list adds an ordered item collection:

class WidgetRichList extends BaseWidget
{
    /**
     * @ORM\OneToMany(targetEntity="WidgetRichListItem", mappedBy="widget",
     *     cascade={"persist", "remove"}, orphanRemoval=true)
     * @ORM\OrderBy({"position" = "ASC"})
     */
    protected $items;

    public function getWidgetName(): string
    {
        return 'richlist';
    }
}

The collection form pattern. This is the heart of the widget. Note by_reference => false and allow_add/allow_delete — without them the item collection will not persist correctly:

$builder->add('items', 'collection', [
    'type'              => new WidgetRichListItemType(),
    'allow_add'         => true,
    'allow_delete'      => true,
    'by_reference'      => false,
    'prototype'         => true,
    'cascade_validation'=> true,
]);

Victoire's backend uses the Twig collection prototype plus JavaScript to clone rows. If your items vanish on save, that pair of options is almost always the cause.

Template override workflow. Never edit the vendor template. Copy it into the app-level override path, which is the standard Symfony bundle override convention Victoire respects:

cp vendor/friendsofvictoire/richlist-widget/Resources/views/Widget/show.html.twig \
   app/Resources/VictoireWidgetRichListBundle/views/Widget/show.html.twig

Then edit the copy. Clear the cache (bin/console cache:clear --env=dev) and reload. If the override does not take effect, the bundle is probably registered under a slightly different logical name — check bin/console debug:twig --filter=richlist for the actual namespace.

Layout variants. Victoire widgets generally expose a cssClass/template selector field. Use it to drive per-widget layout choices in the template:

{% set items = widget.items %}
<ul class="rich-list {{ widget.cssClass }}">
  {% for item in items %}
    <li class="rich-list__item">
      {% if item.image %}<img src="{{ item.image.url }}" alt="{{ item.title }}">{% endif %}
      <h3>{{ item.title }}</h3>
      <div>{{ item.body|raw }}</div>
      {% if item.url %}<a href="{{ item.url }}">{{ item.linkLabel|default('Read more') }}</a>{% endif %}
    </li>
  {% endfor %}
</ul>

Laravel equivalent (what you actually build). If you are porting this to Laravel, the same shape maps cleanly:

Schema::create('rich_list_items', function (Blueprint $table) {
    $table->id();
    $table->foreignId('rich_list_id')->constrained()->cascadeOnDelete();
    $table->string('title');
    $table->text('body')->nullable();
    $table->string('url')->nullable();
    $table->string('image')->nullable();
    $table->unsignedInteger('position')->default(0);
    $table->timestamps();
});
class RichList extends Model
{
    protected $casts = ['items' => 'collection'];
    public function items() { return $this->hasMany(RichListItem::class)->orderBy('position'); }
}
{{-- resources/views/components/rich-list.blade.php --}}
<ul {{ $attributes->merge(['class' => 'rich-list']) }}>
    @foreach ($items as $item)
        <li class="rich-list__item">
            @if ($item->image)<img src="{{ Storage::url($item->image) }}" alt="{{ $item->title }}">@endif
            <h3>{{ $item->title }}</h3>
            <div>{!! $item->body !!}</div>
            @if ($item->url)<a href="{{ $item->url }}">Read more</a>@endif
        </li>
    @endforeach
</ul>

For the editor, a Filament Repeater / Nova Flexible field gives you the exact same UX the Victoire bundle gave in 2016 — with active maintenance.

Integration tip: keep the data model free of presentation. The Victoire bundle mixes widget entity, form, and template in one folder; when you port, split them into model / panel schema / Blade component so a layout change never touches the database.

Gotchas and Tips

  • PHP 8 will break it. The code predates PHP 7.2 typed properties and targets Symfony 2.8/3.x APIs. composer require on a modern stack will either fail or install a decade-old transitive tree. Do not put this in a greenfield project.
  • The widget must be tagged. Registering the bundle alone is not enough — Victoire builds its palette from the victoire_core.widgets config and/or a victoire.widget service tag. If the widget does not appear in the backend "add widget" menu, check bin/console debug:container --tag=victoire.widget.
  • Collection persistence. The two classic failures: missing cascade={"persist"} on the OneToMany (items saved but detached) and missing by_reference => false in the form (mutations not written back). Both present as "the list is empty after I save."
  • Ordering. If the package does not ship an OrderBy, your items render in insertion order and reordering in the UI silently does nothing. Add position explicitly and sort in the template if needed.
  • Template namespace. Overrides fail silently if the path casing is off (VictoireWidgetRichListBundle vs VictoireRichListBundle). The directory must exactly match the bundle's logical name — verify with debug:twig rather than guessing.
  • Translations. Widget labels come from Resources/translations/*.yml. Missing keys show the raw key in the admin UI, which looks like a bug but is just an untranslated label — add victoire_richlist.widget.name to your app translations.
  • Raw HTML. The body field is rich text and rendered with |raw. If you inherit this in production, confirm the editor sanitizes on save; otherwise you have stored XSS on every page using the widget. In Laravel, treat this as the cue to use a sanitizer like mews/purifier before {!! !!}.
  • Extension points are fragile. You can swap the form type via a service alias or override the template, but extending the entity pulls you into Victoire's "business entity / page pattern" machinery, which is the least documented part of the CMS. If you need new fields, fork the widget into your own bundle rather than subclassing.
  • Debugging checklist: bin/console cache:clear, debug:container --tag=victoire.widget, debug:twig, then var/logs/dev.log. Nine out of ten "widget missing / template stale" issues are a stale cache after a config change.
  • Migration advice: treat the bundle as a specification, not a dependency. Read the entity and template (about 200 lines total), then implement a rich_lists / rich_list_items pair plus a Blade component in Laravel. You will spend less time than getting a 2016 Symfony 2.8 bundle to boot, and you will own the code.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package