2

Hello I've created a new element type in a module (a web app within Craft) that I'm developing. I have initially created my models to be craft\db\ActiveRecord and save directly to their tables, but that is not the "craft" way.

I decided to extend from craft\base\Element and do the needful in order to leverage elementindex.html (search, sort, filter), but going to /admin/custom/index gives a "404 Not Found". Do I need to create my own CustomController.php ?

I did the configuration needed in my Module class, as well as creating the Custom.php and CustomQuery.php according to the documentation here

   // CP Routes
    Event::on(
        UrlManager::class,
        UrlManager::EVENT_REGISTER_CP_URL_RULES,
        function (RegisterUrlRulesEvent $event) {
            $event->rules['custom'] = '/app-module/custom/index';
        }
    );

    // CP Nav Items
    Event::on(
        Cp::class,
        Cp::EVENT_REGISTER_CP_NAV_ITEMS,
        function (RegisterCpNavItemsEvent $event) {
            $event->navItems[] = [
                'url' => 'custom',
                'label' => 'Custom',
                'icon' => 'share',
            ];
        }
    );

    // Custom Element Types
    Event::on(Elements::class,
        Elements::EVENT_REGISTER_ELEMENT_TYPES,
        function(RegisterComponentTypesEvent $event) {
            $event->types[] = Custom::class;
        }
    );
1

Since this is a module rather than a plugin, you need to register control panel template roots, like so:

  Event::on(
    View::class,
    View::EVENT_REGISTER_CP_TEMPLATE_ROOTS,
    function (RegisterTemplateRootsEvent $e) {
        $e->roots['app-module'] = __DIR__ . '/templates/cp';
    }
  );

(I've swapped 'custom' for 'app-module' as I think it's a little more clear, but feel free to keep it as 'custom') If your module's src folder does not have a templates/cp directory, create one and add an index.twig to it. Now going to admin/app-module should load the index file you've created. (You'll need to update the EVENT_REGISTER_CP_NAV_ITEMS from 'custom' to 'app-module' to have the CP url match the change I've made here.) However, since you're working with an element, it's probably better to create another directory named after your element. Let's use "Item" as a generic element class name, you might have templates/cp/items/index.twig who's contents might look like this:

{% extends elementType is defined ? '_layouts/elementindex' : '_layouts/cp' %}

{% set elementType = 'modules\\appmodule\\elements\\ItemElement' %}
{% set title = 'My Custom Items'|t('app-module') %}

{% block actionButton %}
 <div id="extra-headers">
    <div class="buttons right">
      <a href="{{ url('app-module/items/new') }}" class="btn submit add icon">
       {{ "New custom item"|t('app-module')}}
      </a>
    </div>
  </div>
{% endblock %}

You don't need to register this URL via the EVENT_REGISTER_CP_URL_RULES, but you will want to for the element edit and creation page. e.g.

Event::on(
    UrlManager::class,
    UrlManager::EVENT_REGISTER_CP_URL_RULES,
    function (RegisterUrlRulesEvent $event) {
        $event->rules['app-module/items/new'] = 'app-module/items/edit-item';
        $event->rules['app-module/items/<itemId:\d+>' => 'app-module/items/edit-item']
    }
);

Here, the key is the URL you will hit in the control panel and the value is the action URL you'll need to create in your module. src/controllers/ItemsController.php, which will have an actionEditItem function.

Hope this helps!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.