Fields (Pro)

There are more than 25 types of fields defined by this plugin.

The field CraftField handles every custom Craft field with the exception of Table, Matrix and Neo fields. Their displayers will display the Craft field associated with them.

Then there are custom fields defined by this plugin that will render a Craft element's native field or attribute :

  • AllowedQty : for variants only
  • Author : for channels and structures only
  • DateCreated
  • DateUpdated
  • Dimensions : for variants only
  • ElementUrl : for entries/categories/assets/products only
  • ExpiryDate : for channels, structures and products only
  • File : for assets only
  • Matrix
  • NeoField : introduced in 4.1
  • PostDate : for entries and products only
  • Price : for variants only
  • Sku : for variants only
  • Stock : for variants only
  • SuperTable : introduced in 4.1
  • Table
  • TagTitle : for tags only
  • Title : for entries/categories/assets/products/variants only
  • UserEmail : For users only
  • UserFirstName : For users only
  • LastLoginDate : For users only
  • UserLastName : For users only
  • UserPhoto : For users only
  • UserUsername : For users only
  • Variants : for products only
  • Weight : for variants only

A field displayer defines how a field is rendered on the front end, each field displayer will handle one type of field. This is controlled by the method getFieldTarget(): string which will return either the class of the Craft field this displayer can handle, or the class of the themes field (like Title, Author etc).

Define a new field

PHP

Define a new field model class, example for a field that will handle the dateCreated of a element :

<?php

use Ryssbowh\CraftThemes\interfaces\LayoutInterface;
use Ryssbowh\CraftThemes\models\Field;

class MyField extends Field
{
    /**
     * @inheritDoc
     */
    public static function getType(): string
    {
        return 'date-created';
    }

    /**
     * @inheritDoc
     */
    public static function shouldExistOnLayout(LayoutInterface $layout): bool
    {
        return true;
    }

    /**
     * @inheritDoc
     */
    public function getHandle(): string
    {
        return 'dateCreated';
    }

    /**
     * @inheritDoc
     */
    public function getName(): string
    {
        return \Craft::t('themes', 'Date created');
    }
}

Register your php field class (implementing FieldInterface) by responding to the event :

Event::on(
    FieldsService::class,
    FieldsService::EVENT_REGISTER_FIELDS,
    function (RegisterFieldsEvent $event) {
        $event->register(MyField::class);
});

Create field automatically on elements

Custom fields (any field that doesn't extend from CraftField) can be created automatically on layouts if you return true to the method shouldExistOnLayout(LayoutInterface $layout). By default this method returns false.

This method won't have any effect for fields that extends CraftField, as they will be created automatically (assuming a Craft field exists on the category group/entry type).

After creating your field you will need to rebuild the fields using the Themes settings or the command craft themes/install so that they are created.

Complex fields

If your field is "complex" (has sub fields for example), you may need a bespoke Vue component to render it in CP :

To hook in the backend Vue system, register a javascript file with a bundle :

Event::on(
    CpDisplayController::class,
    CpDisplayController::EVENT_REGISTER_ASSET_BUNDLES,
    function (RegisterBundles $event) {
        $event->bundles[] = MyBundle::class;
});

This bundle should depend on Ryssbowh\CraftThemes\assets\VueAssets.

Javascript

Your javascript must register an object to window.CraftThemes.fieldComponents and register an object with two keys, component (a Vue component) and clone (the function used to clone the field when creating new view modes)

import Matrix from './components/Matrix.js'; //Regular Vue component
import { merge } from 'lodash';

window.CraftThemes.fieldComponents['matrix'] = {
    component : Matrix,
    clone: function (field, app) {
        let newField = merge({}, field);
        for (let i in field.types) {
            for (let j in field.types[i].fields) {
                newField.types[i].fields[j] = app.config.globalProperties.cloneField(field.types[i].fields[j]);
            }
        }
        return newField;
    }
}

More examples here

Modify displayers

You may also need to modify displayers so that they can handle your field :

Event::on(
    UrlLink::class,
    FieldDisplayerService::EVENT_REGISTER_FIELD_TARGETS,
    function (RegisterDisplayerTargetsEvent $event) {
        $event->targets[] = MyField::class;
});

Eager loading (Pro)

When a view mode is rendered the eager load map will be built to eager load every possible field on that view mode. The map will also contain nested view modes fields (displayers that render other layouts/view modes) and assets transforms. This map will be stored in cache.

The cache is enabled when devMode is off and can be cleared with the following command : ./craft invalidate-tags/themes::eagerLoad, it will be automatically cleared for the relevant view modes when anything is changed in them.

Eager loading will nest until 5 levels, after that it will stop.

Example :

  • View mode 'default' :
    • field entries pointing to view mode 'small' : level 1
    • View mode 'small'
      • Field categories pointing to view mode 'featured' : Level 2
      • View mode 'featured' :
        • Field assets : Level 3

Settings can be controlled by creating the config/themes.php file :

<?php

return [
    'eagerLoad' => false,
    'eagerLoadingCache' => false,
    'maxEagerLoadLevel' => 10
];

All the templates defined by this plugin expect fields to be eager loaded, switching off that feature could result in lots of extra n+1 queries (especially if your displayer cache is off).

You must enable javascript to view this website