Step-by-step guide
This will walk you through the process of creating your first page. In this example we will create the most basic page with just a single component.
Remember all the IDs will be automatically generated, so you will need to pay attention in the example POST requests and use the appropriate IDs
Table of contents
Create a Layout
Every page requires a Layout to be defined. This specifies which UI component will be used as the layout, usually the same for a number of pages. For example a layout may include a logo, a navigation bar and a footer.
In this example we will assume the layout will just include a logo as defined by the front-end application. Because we are choosing that that logo should not be updated by the website user, this will not need to have any data associated with it in the API and should be hosted by the front-end application.
So let’s send a JSON POST request to the API endpoint /_/layouts
:
{
"reference": "primary",
"uiComponent": "PrimaryLayout"
}
You should get a 201 HTTP response with the new resource
{
"@context": "/contexts/Layout",
"@id": "/_/layouts/41c57f7a-9f69-11ea-8188-acde48001122",
"@type": "Layout",
"reference": "primary",
"pages": [],
"createdAt": "2020-05-26T15:55:01+00:00",
"modifiedAt": "2020-05-26T15:55:01+00:00",
"uiComponent": "PrimaryLayout",
"componentGroups": [],
"_metadata": {
"persisted": true
}
}
Create a Page
The page will define a UI component which will display ComponentGroup
resources wherever you have configured it to do so in your front-end application. For example, the page could be a 2-column layout and there would be a ComponentGroup
for each column. It must also define which layout it uses and a reference.
Let’s create the page. Send a JSON POST request to the endpoint /_/pages
:
{
"layout": "/_/layouts/41c57f7a-9f69-11ea-8188-acde48001122",
"reference": "example-page",
"uiComponent": "ExamplePageTemplateComponent",
"title": "My Demo Page",
"metaDescription": "Once upon a time I was learning how to create my resources for an API Component Bundle project."
}
You should get a 201 HTTP response with the new resource
{
"@context": "/contexts/Page",
"@id": "/_/pages/56fd3fe0-9f69-11ea-9d75-acde48001122",
"@type": "Page",
"layout": "/_/layouts/41c57f7a-9f69-11ea-8188-acde48001122",
"reference": "example-page",
"createdAt": "2020-05-26T15:55:36+00:00",
"modifiedAt": "2020-05-26T15:55:36+00:00",
"uiComponent": "ExamplePageTemplateComponent",
"componentGroups": [],
"nested": true,
"title": "My Demo Page",
"metaDescription": "Once upon a time I was learning how to create my resources for an API Component Bundle project.",
"_metadata": {
"persisted": true
}
}
Create a ComponentGroup
The UI component in the front-end application will be looking for a ComponentGroup
resource with a given reference so that it knows which collection of components to display where. In this example we will assume the UI component will only be expecting 1 ComponentGroup
resource with the reference main_body
.
Let’s create this resource by sending a POST request to the endpoint /_/component_groups
{
"reference": "main_body",
"pages": [
"/_/pages/56fd3fe0-9f69-11ea-9d75-acde48001122"
]
}
You should get an HTTP 201 response with the resource
{
"@context": "/contexts/ComponentGroup",
"@id": "/_/component_groups/6866c422-9f69-11ea-a2d3-acde48001122",
"@type": "ComponentGroup",
"reference": "main_body",
"layouts": [],
"pages": [],
"components": [],
"componentPositions": [],
"createdAt": "2020-05-26T15:56:05+00:00",
"modifiedAt": "2020-05-26T15:56:05+00:00",
"_metadata": {
"persisted": true
}
}
Create your Component
This bundle provides you with a simple way to create any component you could want on your website with its associated data. In this example, we will create a simple component which is designed to store and display HTML content. In your front-end you would implement a WYSIWYG editor such as Quill.
Define the Component resource
Let’s create our HtmlComponent class/entity. This is done just as you would if you were creating any API resource for API Platform and Doctrine except you will extend AbstractComponent
.
Create the entity /Entity/HtmlComponent
:
<?php
declare(strict_types=1);
namespace Silverback\ApiComponentsBundle\Tests\Functional\TestBundle\Entity;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Silverback\ApiComponentsBundle\Entity\Core\AbstractComponent;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @author Daniel West <daniel@silverback.is>
*/
#[ApiResource]
#[ORM\Entity]
class HtmlComponent extends AbstractComponent
{
#[Assert\NotBlank]
#[ORM\Column(nullable: false)]
public string $html;
}
…and just like that, you will have an endpoint to be able to create one of these components! We will not dive into detail with the annotations here. It is all very well documented in API Platform and Symfony.
You will have made all your components in the API before your front-end application needs to use them.
Remember to take a look at some very helpful annotations and traits you can use in your components to support more advanced features.
Add the component to your page
Let’s create this component resource now. You could add the component and then add the ComponentPosition
resource to place it within the ComponentGroup. However, in the example below we will add the resource and position it in the same request.
You will notice all components you create are prefixed with /component
.
Send your JSON request to the endpoint /component/html_components
:
{
"html": "<p>Hello Covid World</p>",
"componentPositions": [
{
"componentGroup": "/_/component_groups/6866c422-9f69-11ea-a2d3-acde48001122"
}
],
"uiComponent": "HtmlComponent"
}
You will receive a 201 HTTP response with the resource
{
"@context": "/contexts/HtmlComponent",
"@id": "/component/html_components/27d0eb9c-9f71-11ea-af5a-acde48001122",
"@type": "HtmlComponent",
"html": "<p>Hello Covid World</p>",
"uiComponent": "HtmlComponent",
"componentGroups": [],
"_metadata": {
"persisted": true
}
}
Create a Route
Finally, you will want your page to be accessible via a route/path.
Send your JSON POST request to /_/routes
{
"path": "/example",
"name": "example-route",
"page": "/_/pages/56fd3fe0-9f69-11ea-9d75-acde48001122"
}
And your route will be created and returned
{
"@context": "/contexts/Route",
"@id": "/_/routes/88a9f186-a0b4-11ea-a314-acde48001122",
"@type": "Route",
"createdAt": "2020-05-28T07:26:23+00:00",
"modifiedAt": "2020-05-28T07:26:23+00:00",
"path": "/example",
"name": "example-route",
"redirect": null,
"redirectedFrom": [],
"page": "/_/pages/56fd3fe0-9f69-11ea-9d75-acde48001122",
"pageData": null,
"_metadata": {
"persisted": true
}
}