TasticFieldHandler
The standard data sources in Frontastic are contained in what we call dataSourceTypes
. For example, product-list
and content
are both dataSourceTypes
. If a Frontastic component is defined to retrieve a data source of a certain dataSourceType
, it'll be provided with the corresponding data automatically at the time of rendering. You can extend this mechanism with a TasticFieldHandler to provide a custom dataSourceType
to a Frontastic component in a similar way.
A TasticFieldHandler has previously been known as a custom field handler or a custom stream handler, but the class has always been
TasticFieldHandler
. A Tastic is the short name for a Frontastic component in code.
To provide a custom dataSourceType
, you'll need to follow the steps below to register the TasticFieldHandler in the Frontastic PHP stack:
- Provide an implementation
In order to handle the customdataSourceType
, you'll need to provide an implementation ofFrontastic\Catwalk\FrontendBundle\Domain\TasticFieldHandlerV3
which is the generalized interface for handling all field types and contains 2 methods:
namespace Frontastic\Catwalk\FrontendBundle\Domain;
use Frontastic\Catwalk\ApiCoreBundle\Domain\Context;
abstract class TasticFieldHandlerV3
{
/**
* @return string
*/
abstract public function getType(): string;
/**
* @param mixed $fieldValue
* @return mixed Handled value
*/
abstract public function handle(Context $context, Node $node, Page $page, Tastic $tastic, $fieldValue);
}
The getType()
method should return the type identifier for your dataSourceType
.
You must prefix dataSourceTypes
with your project ID in the form<project-id>-<dataSourceType>
, for example, awesomeshop-stores
if your project is awesomeshop
and your dataSourceType
will provide information about local stores
.
The 2nd method handle()
performs the actual work of handling your dataSourceType
. It's called by Frontastic as soon as a Frontastic component requires a data source of your dataSourceType
.
As parameters, it receives the current application Context
, Node
, Page
, Tastic
, and the $fieldValue
which was configured in the Frontastic studio.
We're still working on this feature. It's not yet possible to assign values to custom data source fields in the Frontastic studio. But even without this possibility, a custom
dataSourceType
can be useful to provide data to a Frontastic component.
The handle()
method is supposed to return the value of the data source that will then be given to the Frontastic component that required it. It can be an arbitrary value type except for 1 constraint: It must be serializable to JSON (that excludes, for example, resource
types). Ideally, you'll return either:
- A simple data object
- An array of scalar values of simple array objects
- Null
- A combination of the above
You might notice that this is also called TasticFieldHandlerV3
. If you previously implemented the TasticFieldHandler or TasticFieldHandlerV2 and it's not using V3, you can use the TasticFieldHandlerAdapter
if you don't want to update to using V3.
- Register your TasticFieldHandler
Now that you've implemented your TasticFieldHandler for yourdataSourceType
, you need to register it in the Symfony service container and apply a tag to it, so it knows what it is.
To do this, go to your services.xml
in one of your project bundles (if there isn't a bundle yet, you can create one using, for example, bin/console frontastic:create:bundle MyDecorators
, see the Creating a backend bundle article for more information) and then add the tag frontend.tasticFieldHandler
to it in a similar way to the below:
<service id="Frontastic\Customer\StorefinderBundle\Domain\StreamHandler">
<argument type="service" id="Frontastic\Customer\StorefinderBundle\Domain\StorefinderService" />
<tag name="frontend.tasticFieldHandler"/>
</service>
In this example, a TasticFieldHandler is registered for implementing a store finder. The implementation itself is rather slim and dispatches all work to a service. This gives you the possibility to unleash the full power of Frontastic, Symfony, and your own microservice APIs within a TasticFieldHandler.
- Use the
dataSourceType
Now you need to add your TasticFieldHandler to a Frontastic component schema. You must set thetype
todataSource
and then set thedataSourceType
to the type that you created in the first step, for example:
{
"tasticType": "awesomeshop-store-finder",
"name": "Storefinder",
"category": "Awesome Shop",
"icon": "store",
"schema": [
{
"name": "General",
"fields": [
{
"label": "Stores",
"field": "dataSource",
"type": "dataSource",
"dataSourceType": "awesomeshop-stores",
"default": null,
"required": false
}
]
}
]
}
Configure custom data sources
You can enable custom data sources to be configurable in the Frontastic studio if you've had this feature enabled (contact our Support team if you'd like the customStreamConfig
enabled).
To do this, follow the steps below.
For this example, we'll be implementing custom dataSourceType
of frontastic/weather
, so our Frontastic component schema would look like the below:
{
//...
"label": "Weather data source",
"field": "weather",
"type": "dataSource",
"dataSourceType": "frontastic/weather",
"required": true
//...
}
-
Open the Frontastic studio, click Developer, and then TasticFieldHandler
-
Click Create schema, this will open the schema editor
- Input your JSON schema, for example, we'll copy the below into the schema editor:
The field value of
customStreamType
must match thedataSourceType
field from the Frontastic component schema.
{
"customStreamType": "frontastic/weather",
"name": "Weather",
"category": "Content",
"icon": "wb_sunny",
"schema": [
{
"name": "Location",
"fields": [
{
"label": "Default city",
"field": "city",
"type": "string",
"default": "",
"translatable": false
},
{
"label": "Default country code",
"field": "country",
"type": "string",
"default": "DE",
"translatable": false
}
]
}
]
}
You'll see that we've added 2 fields (Default city
and Default country code
), these are the fields that are configurable when a Frontastic component is added to a page and would look like the below:
The values configured here will be passed as the $fieldValue
to the TasticFieldHandler.
- Click Validate to check for errors
- Click Publish
You can edit your schema once published if you need to. Click the name of your custom stream to open the right-hand drawer for options:
If you make any changes to your schema, ensure it's backwards compatible before saving.
Accessing the request
We generally discourage accessing the request from a service, however, until we can offer a better way to access such information it can be used as a workaround.
Since a field handler is a normal Symfony service, you can get any service injected to dispatch work to. This also holds true for the RequestStack
which allows you to get your hands on the currently processed request to access URL parameters and much more:
namespace Frontastic\Customer\StorefinderBundle\Domain;
use Symfony\Component\HttpFoundation\RequestStack;
use Frontastic\Catwalk\FrontendBundle\Domain\TasticFieldHandler;
use Frontastic\Catwalk\FrontendBundle\Domain\Stream;
use Frontastic\Catwalk\ApiCoreBundle\Domain\DataRepository;
use Frontastic\Catwalk\ApiCoreBundle\Domain\Context;
use Frontastic\Common\ProductApiBundle\Domain\ProductApi\Locale;
class StoresFieldHandler
extends TasticFieldHandlerV3
{
private $service;
private $requestStack;
public function __construct(StorefinderService $service, RequestStack $requestStack)
{
$this->service = $service;
$this->requestStack = $requestStack;
}
public function getType(): string
{
return 'awesomeshop-stores';
}
public function handle(Context $context, Node $node, Page $page, Tastic $tastic, $fieldValue)
{
$locationId = $this->requestStack->getCurrentRequest()->get('location', null);
if (!$locationId) {
return null;
}
$locale = Locale::createFromPosix($context->locale);
return $this->service->getStores($locale->territory, $locationId);
}
}
In this example, the RequestStack
is asked for the current request to fetch the URL parameter location
. If this isn't set, the dataSourceType
contains nothing. Otherwise, the corresponding domain service is used to determine stores for the dataSourceType
.
Updated 12 months ago