The CWA is in heavy development
Create a component
Let's say we want a user to be able to add a title to their website as a UI component that you have styled.
https://localhost/login
to use the management systemBack-End (API)
First, you should define your back-end and what data in your UI component you want a website administrator to be able to edit. For this component, you know you will want the user to edit the title text.
Create your class extending AbstractComponent
:
<?php
namespace App\Entity;
use Silverback\ApiComponentsBundle\Entity\Core\AbstractComponent;
class Title extends AbstractComponent
{
public ?string $title = null;
}
Now we will add some PHP annotation to mark this as an API resource and map it as a database entity. We have also defined this resource to publish to Mercure for real-time updates.
<?php
...
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
#[Orm\Entity]
#[ApiResource(mercure: true)]
class Title extends AbstractComponent
{
#[Orm\Column(type: 'text', nullable: true)]
public ?string $title = null;
}
Then, we can add the annotation provided by the ApiComponentsBundle
Symfony bundle which provides extensions for more advanced functionality.
<?php
...
use Silverback\ApiComponentsBundle\Annotation as Silverback;
use Silverback\ApiComponentsBundle\Entity\Utility\PublishableTrait;
#[Silverback\Publishable]
#[Orm\Entity]
#[ApiResource(mercure: true)]
class Title extends AbstractComponent
{
use PublishableTrait;
#[Assert\NotBlank(groups: ['Title:published'])]
#[Orm\Column(type: 'text', nullable: true)]
public ?string $title = null;
}
Finally, we can easily add validation to the title so that a published version cannot have a blank title. Your final class should look like this.
<?php
namespace App\Entity;
use Silverback\ApiComponentsBundle\Entity\Core\AbstractComponent;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Silverback\ApiComponentsBundle\Annotation as Silverback;
use Silverback\ApiComponentsBundle\Entity\Utility\PublishableTrait;
use Symfony\Component\Validator\Constraints as Assert;
#[Silverback\Publishable]
#[Orm\Entity]
#[ApiResource(mercure: true)]
class Title extends AbstractComponent
{
use PublishableTrait;
#[Orm\Column(type: 'text', nullable: true)]
#[Assert\NotBlank(groups: ['Title:published'])]
public ?string $title = null;
}
bin/console doctrine:migrations:diff
and bin/console doctrine:migrations:migrate
once you have checked the migration meets your needs.Easy right? Now let's make the front-end.
Front-End
If you are familiar with creating Vue components, the following code examples will look very straight forward.
nuxt.config.ts
fileComponent
With our useCwaResource
composable it is very easy to create your UI component. The composable provides many useful utilities so you can access your resource data, define the required properties and expose the required data for our internal management system.
<template>
<h1 class="text-primary text-4xl font-extrabold">
{{ resource?.data?.title || 'No Title' }}
</h1>
</template>
<script setup lang="ts">
import { toRef } from 'vue'
import { useCwaResource } from '#imports'
import type { IriProp } from "#cwa/runtime/composables/cwa-resource";
const props = defineProps<IriProp>()
const { getResource, exposeMeta } = useCwaResource(toRef(props, 'iri'))
const resource = getResource()
defineExpose(exposeMeta)
</script>
Admin
Within the Title
directory, you can create an admin
folder to create new tabs for the component manager toolbar.
Here we can use 2 more useful composables. useCwaResourceManagerTab
allows you to expose information, name your tab, set the order etc.
useCwaResourceModel
takes an argument for the component identifier, and another for the field to update in the API.
We also have some commonly used UI components to use within the component manager toolbar.
Here is a complete example for managing your new Title component.
<template>
<CwaUiFormLabelWrapper label="Title">
<CwaUiFormInput v-model="titleModel.model.value" />
</CwaUiFormLabelWrapper>
</template>
<script setup lang="ts">
import { useCwaResourceManagerTab, useCwaResourceModel } from '#imports'
const { exposeMeta, iri } = useCwaResourceManagerTab({ name: 'Title' })
const titleModel = useCwaResourceModel<string>(iri, 'title')
defineExpose(exposeMeta)
</script>
Congratulations!
That's it! 🚀
If you go to your website, you can how add a new Title component, see it become a draft as you edit it and then publish when ready. If you have another incognito window open with on the page, when you publish your new live version, you'll see a notification appear to update your view.