Concrete CMS Custom Pages

User
also how to adapt default concrete cms pages like list page add/edit page in custom packages
Assistant
To adapt default **Concrete CMS pages** like **list, add, and edit** pages in your **custom package**, you can follow this approach. Concrete CMS provides a robust way to reuse its built-in CRUD and form handling patterns by extending core classes.

### ✅ Step-by-step to Create List / Add / Edit Pages in a Custom Package

#### 1. **Create Dashboard Single Pages**

Inside your package’s `controller.php` file:

public function install()
{
    $pkg = parent::install();

    // Create single pages
    ConcreteCorePageSingle::add('/dashboard/your_section/list', $pkg);
    ConcreteCorePageSingle::add('/dashboard/your_section/add', $pkg);
    ConcreteCorePageSingle::add('/dashboard/your_section/edit', $pkg);
}

#### 2. **Create Page Controllers**

Create a directory inside your package:

packages/your_package/controllers/single_page/dashboard/your_section/

Then create:

– `list.php`
– `add.php`
– `edit.php`

Example for `list.php`:

namespace ConcretePackageYourPackageControllerSinglePageDashboardYourSection;

use ConcreteCorePageControllerDashboardPageController;
use ConcreteCoreDatabaseConnectionConnection;

class List extends DashboardPageController
{
    public function view()
    {
        $db = $this->app->make(Connection::class);
        $items = $db->fetchAll("SELECT * FROM your_table ORDER BY id DESC");

        $this->set('items', $items);
    }
}

#### 3. **Create the View Templates**

Under:

packages/your_package/single_pages/dashboard/your_section/

Create:
– `list.php`
– `add.php`
– `edit.php`

Example for `list.php`:

<?php defined('C5_EXECUTE') or die("Access Denied."); ?>
<h2>Item List</h2>
<a class="btn btn-primary" href="<?= URL::to('/dashboard/your_section/add') ?>">Add New</a>
<table class="table">
    <thead>
        <tr><th>ID</th><th>Title</th><th>Actions</th></tr>
    </thead>
    <tbody>
        <?php foreach ($items as $item): ?>
            <tr>
                <td><?= $item['id'] ?></td>
                <td><?= h($item['title']) ?></td>
                <td>
                    <a href="<?= URL::to('/dashboard/your_section/edit', $item['id']) ?>" class="btn btn-sm btn-secondary">Edit</a>
                </td>
            </tr>
        <?php endforeach; ?>
    </tbody>
</table>

#### 4. **Handle Form Submission (Add/Edit)**

In `add.php` and `edit.php` controller files, add logic like:

public function submit()
{
    $token = $this->app->make('token');
    if (!$token->validate('add_item')) {
        $this->error->add(t("Invalid CSRF token."));
        return;
    }

    $title = $this->post('title');

    if (!$title) {
        $this->error->add(t("Title is required."));
    }

    if (!$this->error->has()) {
        $db = $this->app->make(Connection::class);
        $db->insert('your_table', ['title' => $title]);

        $this->flash('success', 'Item added successfully.');
        return $this->redirect('/dashboard/your_section/list');
    }
}

And in `add.php` view:

<form method="post" action="<?= $view->action('submit') ?>">
    <?= $token->output('add_item') ?>
    <div class="form-group">
        <label>Title</label>
        <input class="form-control" name="title" />
    </div>
    <button class="btn btn-success">Save</button>
</form>

### 🧠 Optional: Reuse Core Components

You can also extend existing Concrete CMS form helpers and dashboard page layout elements to keep your UI consistent.

If you share the exact model or table name you're using, I can give you full working code with real values (e.g., `Feed`, `Product`, etc.).

User
I am talking about adopt concrete cms design
Assistant
Got it! You want to **adopt the default Concrete CMS dashboard design** (styles, layout, components) for your **list, add, and edit pages** in a **custom package**.

Here’s how to do it **the Concrete CMS way**, so your pages look and behave like native dashboard pages:

## ✅ 1. Use Dashboard Layout Structure

Wrap your views in Concrete CMS's dashboard panel styles.

### Example: `list.php` View

<?php defined('C5_EXECUTE') or die("Access Denied."); ?>
<?php
use ConcreteCoreViewView;
use ConcreteCoreSupportFacadeUrl;
use ConcreteCoreApplicationServiceUserInterface;

$app = ConcreteCoreSupportFacadeApplication::getFacadeApplication();
/** @var UserInterface $ui */
$ui = $app->make(UserInterface::class);
?>

<div class="ccm-ui">
    <div class="dashboard-header-buttons">
        <a href="<?= Url::to('/dashboard/your_section/add') ?>" class="btn btn-primary"><?= t('Add New') ?></a>
    </div>

    <table class="table table-striped">
        <thead>
            <tr>
                <th><?= t('ID') ?></th>
                <th><?= t('Title') ?></th>
                <th><?= t('Actions') ?></th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($items as $item): ?>
                <tr>
                    <td><?= $item['id'] ?></td>
                    <td><?= h($item['title']) ?></td>
                    <td>
                        <a href="<?= Url::to('/dashboard/your_section/edit', $item['id']) ?>" class="btn btn-sm btn-secondary">
                            <?= t('Edit') ?>
                        </a>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>

## ✅ 2. Use Concrete CMS Form Helpers for Consistency

### Example: `add.php` View

<?php defined('C5_EXECUTE') or die("Access Denied."); ?>
<?php
use ConcreteCoreFormServiceForm;
use ConcreteCoreSupportFacadeUrl;

$form = app(Form::class);
?>

<div class="ccm-ui">
    <form method="post" action="<?= $view->action('submit') ?>">
        <?= $token->output('add_item') ?>

        <fieldset>
            <legend><?= t('Add Item') ?></legend>

            <div class="form-group">
                <?= $form->label('title', t('Title')) ?>
                <?= $form->text('title') ?>
            </div>

            <div class="form-group">
                <button class="btn btn-success"><?= t('Save') ?></button>
                <a href="<?= Url::to('/dashboard/your_section/list') ?>" class="btn btn-secondary"><?= t('Cancel') ?></a>
            </div>
        </fieldset>
    </form>
</div>

## ✅ 3. Add Flash Messages & Error Handling

Concrete CMS uses the `message()` function or `$error`, `$message` in controller to pass alerts.

### In your controller:

public function view()
{
    $this->set('message', $this->flash('success'));
}

### In your view:

<?php if (isset($message)) { ?>
    <div class="alert alert-success"><?= h($message) ?></div>
<?php } ?>

<?php if (isset($error) && $error->has()) {
    echo $error->output();
} ?>

## ✅ 4. Use Core Assets

Concrete CMS uses Bootstrap, jQuery, and its own styles. Make sure your layout is wrapped with:

<div class="ccm-ui">
    <!-- Your dashboard page content -->
</div>

This ensures everything inside matches the admin panel’s design system.

## ✅ 5. Optional: Extend Core Controllers

If you want to adopt native logic (e.g. pagination, search filters), you can extend:

use ConcreteCorePageControllerDashboardPageController;

class List extends DashboardPageController
{
    // your logic
}

Would you like a **full working list/add/edit page set** with styling and data fetching based on a specific table or model like `Feeds`? I can scaffold that for you right away.

User
how to add button in header section of the page created in custom package in concrete cms 9 defaut page header section
Assistant
To **add a button in the header section** of a **custom dashboard page** in a **Concrete CMS 9 package**, the correct way is to use the built-in method provided by the `DashboardPageController`:

## ✅ Use `$this->set('headerMenuButton')` in Your Controller

Concrete CMS dashboard pages support a **header menu area**. You can inject buttons into it using a controller variable named `headerMenuButton`.

### 🧩 Step-by-Step:

### 1. **In your page controller** (`list.php`, `edit.php`, etc.):

use ConcreteCorePageControllerDashboardPageController;
use ConcreteCoreSupportFacadeUrl;

class List extends DashboardPageController
{
    public function view()
    {
        $url = Url::to('/dashboard/your_section/add');
        $this->set('headerMenuButton', [
            [
                'url' => $url,
                'label' => t('Add Item'),
                'icon' => 'plus',
                'class' => 'btn-primary',
            ]
        ]);
    }
}

### 2. **In your `list.php` view**, **you don’t need to add the button manually**
Concrete automatically renders the `headerMenuButton` in the page’s header **above the title**, just like core pages.

But if you are overriding the dashboard layout, and want to render it manually (not recommended unless you’ve customized the layout), you can do:

<?php if (isset($headerMenuButton)) {
    foreach ($headerMenuButton as $button) { ?>
        <div class="float-end">
            <a class="btn <?= $button['class'] ?>" href="<?= $button['url'] ?>">
                <i class="fas fa-<?= $button['icon'] ?>"></i> <?= $button['label'] ?>
            </a>
        </div>
    <?php }
} ?>

## 🧪 Example: Full Controller with Header Button

namespace ConcretePackageYourPackageControllerSinglePageDashboardYourSection;

use ConcreteCorePageControllerDashboardPageController;
use ConcreteCoreSupportFacadeUrl;
use ConcreteCoreDatabaseConnectionConnection;

class List extends DashboardPageController
{
    public function view()
    {
        $db = $this->app->make(Connection::class);
        $items = $db->fetchAll("SELECT * FROM your_table");

        $this->set('items', $items);

        $this->set('headerMenuButton', [
            [
                'url' => Url::to('/dashboard/your_section/add'),
                'label' => t('Add Item'),
                'icon' => 'plus',
                'class' => 'btn-primary',
            ]
        ]);
    }
}

## 🎯 Result

Your button will appear **next to the page title** in the standard Concrete CMS dashboard header section — styled and placed just like core pages (e.g., “Add Page” in Pages, “Add User” in Members).

Let me know if you want to add **multiple buttons**, a **dropdown**, or customize the layout further — I can give you full code for that too.

User
NO I want to add here default header proviedd by concrete cms for packga eapgess
Assistant
Thanks for the screenshot — now it's 100% clear.

You're referring to the **default Concrete CMS 9 dashboard page header**, where the **title appears with a bookmark icon** and **no visible buttons**, and you want to **add a button next to that heading** (in the top-right corner of the header bar — just like “Add User” or “Add Page” buttons on core pages).

## ✅ The Correct Concrete CMS 9 Way

Concrete CMS 9 uses a view variable called `headerMenuButton` (or `headerMenuButtons`) which you **set in the controller** — and Concrete will **automatically render the buttons in that header bar** (next to "Shopping Feed" in your case).

## 🧩 Implementation

### ✅ 1. Set the Button in Your Controller

use ConcreteCorePageControllerDashboardPageController;
use ConcreteCoreSupportFacadeUrl;

class ShoppingFeed extends DashboardPageController
{
    public function view()
    {
        $this->set('headerMenuButton', [
            [
                'url' => Url::to('/dashboard/shopping_feed/add'),
                'label' => t('Add Feed'),
                'icon' => 'plus',
                'class' => 'btn-primary',
            ]
        ]);
    }
}

> ✅ Make sure your controller extends `DashboardPageController`.

### ✅ 2. That’s it! **You don’t need to add the button in the view**
Concrete CMS will automatically place the button in the top-right of the default dashboard header (next to “Shopping Feed”).

## ✅ Multiple Buttons?

If you want multiple buttons:

$this->set('headerMenuButton', [
    [
        'url' => Url::to('/dashboard/shopping_feed/add'),
        'label' => t('Add Feed'),
        'icon' => 'plus',
        'class' => 'btn-primary',
    ],
    [
        'url' => Url::to('/dashboard/shopping_feed/settings'),
        'label' => t('Settings'),
        'icon' => 'cog',
        'class' => 'btn-secondary',
    ]
]);

## ✅ Bonus: Ensure You’re Using Concrete’s Default Header

Make sure:
– You are **not overriding the layout** (`single_pages/dashboard/…/yourpage.php`)
– You are **not using a custom view template** that omits the Concrete CMS “ structure

The layout should start like:

<?php defined('C5_EXECUTE') or die("Access Denied."); ?>
<div class="ccm-ui">
    <!-- Concrete CMS will inject the page title and headerMenuButton here -->

Let me know if your button still doesn’t show up — I can help you verify if it’s a controller or view override issue.

Leave a Comment

Your email address will not be published. Required fields are marked *