Components Basics
Creating
To create a new component all you have to do is just to create two files with the same name: ComponentName.html
for template and ComponentName.php
for code logic.
Please note: both files should be in the same folder.
Inside your php file create a class derived from Viewi\Components\BaseComponent
For example, let's create Counter
component.
viewi-app/Components/Views/Counter/Counter.php
<?php

namespace Components\Views\Counter;

use Viewi\Components\BaseComponent;

class Counter extends BaseComponent
{
 public int $count = 0;

 public function increment()
 {
 $this->count++;
 }
}
viewi-app/Components/Views/Counter/Counter.html
<button (click)="increment">Clicked $count times.</button>
From now on you can use it as a tag with the same name as your class name: <Counter />
Reusing Components
You can reuse components as many times as you want. Each of them will have their own scope of data and reactive flow. For example:
<Counter />
<Counter />
<Counter />
The result:
Passing Data through Properties
You can pass data to the child component using html attributes. It can pass literals like strings, numbers, booleans or you can pass an expression.
For example, let's create HelloMessage
component:
<?php

namespace Application\Components\Views\Demo;

use Viewi\Components\BaseComponent;

class HelloMessage extends BaseComponent
{
 public string $name;
}
<div>Hello $name</div>
And now we can pass data to the component as a custom attribute:
<HelloMessage name="John Smith" />
<HelloMessage name="Viewi" />
<HelloMessage name="{getFullName()}" />
The result:
Dynamic Components
In case you want to define your component name dynamically at runtime you can use dynamic component syntax.
For example:
class ComponentsBasics extends BaseComponent
{
 public $currentPage = 'HelloMessage';
}
<$currentPage name="Dynamic Component" />
The result:
Slots
Quite often you will need to pass the content into child component through inner HTML like this:
<Notification>
 <i>Karolina</i> sent you a message.
</Notification>
This can be easily achieved with a special slot
tag, like this:
Notification.html
<div>
 <strong>New notification:</strong>
 <slot></slot>
</div>
The result:
Named Slots
Sometimes you will need to pass different contents into different places to render. A good example for this case is layout. Consider we want something like this:
<div class="header">
 <!-- header content here -->
</div>
<main>
 <!-- main content here -->
</main>
<footer>
 <!-- footer content here -->
</footer>
For that cases a slot
tag can be used with a name
attribute to define where each content belongs to. To specify content for each slot
use slotContent
tag with a name
attribute.
Content from slotContent
goes to slot
with the same name. The rest of the content (outside slotContent) goes to slot
without name
attribute (slot by default).
For example:
BaseLayout.html
<div class="header">
 <slot name="header"></slot>
</div>
<main>
 <slot></slot>
</main>
<footer>
 <slot name="footer"></slot>
</footer>
Using BaseLayout
:
<BaseLayout>
 <slotContent name="header">
 This is my header content
 </slotContent>
 <p>
 Some blog post
 </p>
 <slotContent name="footer">
 <p>Some footer links and copyright</p>
 </slotContent>
</BaseLayout>
The result:
Some blog post
Fallback Content
You can set a default content in case if no content is provided. Just place fallback content inside a slot
tag:
<button>
 <slot>Submit</slot>
</button>
Then use it without content:
<SubmitButton></SubmitButton>
Will generate:
Or with provided content:
<SubmitButton>
 Save
</SubmitButton>
Will generate:
Using with if and foreach
You can use foreach
with components as well as if
, else
, else-if
:
Let's say you have a PostComponent
component:
class PostComponent extends BaseComponent
{
 public string $content;
}
<p>$content</p>
You can use it with foreach
:
class ComponentsBasics extends BaseComponent
{
 public array $posts = [
 'Viewi is awesome!',
 'Lorem ipsum dolor sit amet'
 ];
}
<PostComponent foreach="$posts as $post" content="$post"></PostComponent>
Will generate:
Viewi is awesome!
Lorem ipsum dolor sit amet
And this:
<PostComponent if="true" content="Viewi is awesome!"></PostComponent>
Will generate:
Viewi is awesome!