Skip to content

Commit

Permalink
Rename register component twig function to prepare
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-schranz committed Sep 25, 2020
1 parent 594b6d1 commit 32e3487
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 33 deletions.
87 changes: 73 additions & 14 deletions docs/component.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Web Component Extension

[DEMO](https://github.com/sulu/web-js-twig-demo)

The web component twig extension in connection with [web-js](https://github.com/sulu/web-js)
gives you a simple and efficient way to handle your javascript components over twig.

Expand All @@ -18,36 +20,93 @@ If autoconfigure is not active you need to tag it with [twig.extension](https://
## Usage
You can get the registered components and service call and call the
[web-js](https://github.com/sulu/web-js) function which is recommended to be used with it.
Every component is represented by a DOM element the `prepare_component` function will generate a unique id
which need to set on the DOM element.

At the bottom of your HTML Document you call the [web-js](https://github.com/sulu/web-js) functions
to start the components you have prepared before.

With the `component_list` twig function you can also add only specific html when really needed.

```twig
{# Registering a component #}
<div id="{{ register_component('component') }}">
<div id="{{ prepare_component('component') }}">
Content
</div>
{# Registering a component with options #}
<button id="{{ register_component('modal-button', { text: 'Hello Hikaru Sulu' }) }}">
<button id="{{ prepare_component('modal-button', { text: 'Hello Hikaru Sulu' }) }}">
Say Hello
</button>
{# Start components and run service functions #}
<script>
web.startComponents({{ get_components() }});
</script>
```

### Calling services

Sometimes you just want to call a `web-js` service function.
This can be achieved the following way:

```twig
{# Call a service function #}
{% do call_service('service', 'function') %}
{% do prepare_service_call('service', 'function') %}
{# Call a service function with arguments #}
{% do call_service('api', 'send', ['Hello']) %}

{# Output Html which is needed once by a specific component #}
{% if 'component' in get_component_list() %}
<script id="component-template" type="text/html">
<div>Template</div>
</script>
{% endif %}
{% do prepare_service_call('api', 'setApiKey', [MY_API_KEY]) %}
{# Start components and run service functions #}
<script>
web.startComponents({{ get_components() }});
web.callServices({{ get_services() }});
</script>
```

### Force specific id

If you don't want to autogenerate an ID you can give it as an option:

```twig
<div id="{{ prepare_component('component', { id: 'my-special-id' }) }}">
Content
</div>
```

### Handling ESI

As ESI are own sub request which does not know about the main request ESI need to be handled special.
So if you want to use `web-js` components inside ESI you need to add the following to your `base.html.twig`.

```twig
<head>
{# ... #}
<script>
/* this array will be filled with esi components */
var components = [];
</script>
</head>
<body>
{# ... #}
{# Start components and run service functions #}
<script>
web.startComponents(components.concat({{ get_components() }}));
</script>
</body>
```

In the ESI Template you need to add the following:

```twig
{# before first component: #}
{% do set_component_prefix('unique_prefix') %}
{# ... your twig template with prepare_component calls here #}
{# bottom of your esi template: #}
<script>
components = components.concat({{ get_components() }});
</script>
```
44 changes: 41 additions & 3 deletions src/ComponentExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,20 @@ class ComponentExtension extends AbstractExtension
public function getFunctions()
{
return [
new TwigFunction('register_component', [$this, 'registerComponent']),
new TwigFunction('register_component', [$this, 'registerComponent'], ['deprecated' => true]),
new TwigFunction('prepare_component', [$this, 'prepareComponent']),
new TwigFunction('get_components', [$this, 'getComponents'], ['is_safe' => ['html']]),
new TwigFunction('get_component_list', [$this, 'getComponentList'], ['is_safe' => ['html']]),
new TwigFunction('call_service', [$this, 'callService']),
new TwigFunction('prepare_service_call', [$this, 'prepareServiceCall'], ['deprecated' => true]),
new TwigFunction('get_services', [$this, 'getServices'], ['is_safe' => ['html']]),
new TwigFunction('get_service_list', [$this, 'getServiceList'], ['is_safe' => ['html']]),
new TwigFunction('set_component_prefix', [$this, 'setComponentPrefix']),
];
}

/**
* Register a new component and get a unique id.
* Prepare a new component and get a unique id.
*
* @param string $name
* @param mixed[]|null $options
Expand All @@ -67,6 +69,25 @@ public function getFunctions()
* @return string
*/
public function registerComponent(string $name, ?array $options = null, ?string $prefix = ''): string
{
@trigger_error(
__METHOD__.' is deprecated and will be removed in sulu/web-twig 3.0 use "prepareComponent" instead.',
E_USER_DEPRECATED
);

return $this->prepareComponent($name, $options, $prefix);
}

/**
* Prepare a new component and get a unique id.
*
* @param string $name
* @param mixed[]|null $options
* @param string $prefix
*
* @return string
*/
public function prepareComponent(string $name, ?array $options = null, ?string $prefix = ''): string
{
if (!isset($this->instanceCounter[$name])) {
$this->instanceCounter[$name] = 0;
Expand Down Expand Up @@ -137,13 +158,30 @@ public function getComponentList(bool $jsonEncode = false)
}

/**
* Call a service function.
* Prepare a service call.
*
* @param string $name
* @param string $function
* @param mixed[] $parameters
*/
public function callService(string $name, string $function, array $parameters = []): void
{
@trigger_error(
__METHOD__.' is deprecated and will be removed in sulu/web-twig 3.0 use "prepareServiceCall" instead.',
E_USER_DEPRECATED
);

$this->prepareServiceCall($name, $function, $parameters);
}

/**
* Prepare a service call.
*
* @param string $name
* @param string $function
* @param mixed[] $parameters
*/
public function prepareServiceCall(string $name, string $function, array $parameters = []): void
{
$this->services[] = [
'name' => $name,
Expand Down
34 changes: 18 additions & 16 deletions tests/Unit/ComponentExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function setUp(): void

public function testRegisterComponent(): void
{
$this->assertSame('test-1', $this->componentExtension->registerComponent('test'));
$this->assertSame('test-1', $this->componentExtension->prepareComponent('test'));

$components = $this->componentExtension->getComponents();
$this->assertNotFalse($components);
Expand All @@ -48,7 +48,8 @@ public function testRegisterComponent(): void

public function testRegisterMultipleComponent(): void
{
$this->assertSame('test-1', $this->componentExtension->registerComponent('test'));
$this->assertSame('test-1', $this->componentExtension->prepareComponent('test'));
// this deprecated registerComponent function
$this->assertSame('test-2', $this->componentExtension->registerComponent('test'));

$components = $this->componentExtension->getComponents();
Expand All @@ -73,8 +74,8 @@ public function testRegisterMultipleComponent(): void
public function testRegisterPrefix(): void
{
$this->componentExtension->setComponentPrefix('partial-');
$this->assertSame('partial-test-1', $this->componentExtension->registerComponent('test'));
$this->assertSame('partial-test-2', $this->componentExtension->registerComponent('test'));
$this->assertSame('partial-test-1', $this->componentExtension->prepareComponent('test'));
$this->assertSame('partial-test-2', $this->componentExtension->prepareComponent('test'));

$components = $this->componentExtension->getComponents();
$this->assertNotFalse($components);
Expand All @@ -97,7 +98,7 @@ public function testRegisterPrefix(): void

public function testRegisterCustomIdComponent(): void
{
$this->assertSame('custom', $this->componentExtension->registerComponent('test', ['id' => 'custom']));
$this->assertSame('custom', $this->componentExtension->prepareComponent('test', ['id' => 'custom']));
$components = $this->componentExtension->getComponents();
$this->assertNotFalse($components);
$this->assertSame(
Expand All @@ -114,7 +115,7 @@ public function testRegisterCustomIdComponent(): void

public function testRegisterOptionComponent(): void
{
$this->assertSame('test-1', $this->componentExtension->registerComponent('test', ['option1' => 'value1', 'option2' => 'value2']));
$this->assertSame('test-1', $this->componentExtension->prepareComponent('test', ['option1' => 'value1', 'option2' => 'value2']));

$components = $this->componentExtension->getComponents();
$this->assertNotFalse($components);
Expand All @@ -135,7 +136,7 @@ public function testRegisterOptionComponent(): void

public function testRegisterComponentArray(): void
{
$this->assertSame('test-1', $this->componentExtension->registerComponent('test'));
$this->assertSame('test-1', $this->componentExtension->prepareComponent('test'));

/** @var array<int, array{name: string, id: string, options: mixed}> $components */
$components = $this->componentExtension->getComponents(false);
Expand All @@ -156,7 +157,7 @@ public function testRegisterComponentArray(): void

public function testRegisterComponentClear(): void
{
$this->assertSame('test-1', $this->componentExtension->registerComponent('test'));
$this->assertSame('test-1', $this->componentExtension->prepareComponent('test'));

// Get components without clearing them.
$components = $this->componentExtension->getComponents(true, false);
Expand Down Expand Up @@ -192,10 +193,10 @@ public function testRegisterComponentClear(): void

public function testComponentList(): void
{
$this->componentExtension->registerComponent('test');
$this->componentExtension->registerComponent('test');
$this->componentExtension->registerComponent('test2');
$this->componentExtension->registerComponent('test3');
$this->componentExtension->prepareComponent('test');
$this->componentExtension->prepareComponent('test');
$this->componentExtension->prepareComponent('test2');
$this->componentExtension->prepareComponent('test3');

$componentList = $this->componentExtension->getComponentList();

Expand All @@ -206,7 +207,7 @@ public function testComponentList(): void

public function testCallService(): void
{
$this->componentExtension->callService('service', 'function', ['key' => 'value']);
$this->componentExtension->prepareServiceCall('service', 'function', ['key' => 'value']);

$this->assertSame(
json_encode([
Expand All @@ -224,9 +225,10 @@ public function testCallService(): void

public function testGetServices(): void
{
$this->componentExtension->callService('service', 'function', ['key' => 'value']);
$this->componentExtension->callService('service2', 'function', ['key' => 'value']);
$this->componentExtension->callService('service2', 'function', ['key' => 'value']);
$this->componentExtension->prepareServiceCall('service', 'function', ['key' => 'value']);
$this->componentExtension->prepareServiceCall('service2', 'function', ['key' => 'value']);
$this->componentExtension->prepareServiceCall('service2', 'function', ['key' => 'value']);
// test deprecated service call
$this->componentExtension->callService('service3', 'function', ['key' => 'value']);

$servicesList = $this->componentExtension->getServiceList();
Expand Down

0 comments on commit 32e3487

Please sign in to comment.