Reusing layouts

Viewi supports layout sharing between different components. And if you navigate to another page component, Viewi will reuse same layout and will preserve its state, including child components of that layout.

In other words - you do not need to worry about nesting your routes, preserving shared contents, menus, headers, footers, and animations or jumpy pages.

For example, this Layout component can be reused with its state and content preservation. For demonstration we will use timer that will keep updating the page each second:

<?php

namespace Components\Views\Layouts;

use Viewi\Components\BaseComponent;

class Layout extends BaseComponent
{
    public string $title = 'Viewi';

    public int $timerId = 0;
    public int $seconds = 0;

    public function init()
    {
        $this->seconds = 500;
        <<<'javascript'
        this.timerId = setInterval(() => $this.tick(), 1000);
        javascript;
    }

    public function destroy()
    {
        <<<javascript
        clearInterval(this.timerId);
        javascript;
    }

    public function tick()
    {
        $this->seconds++;
        <<<'javascript'
        console.log('Layout time ' + $this.seconds);
        javascript;
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>
        $title | Viewi
    </title>
</head>

<body>
    <div id="sidebar">
        <MenuBar />
    </div>
    <h2><i>Layout time: $seconds</i></h2>
    <DemoContainer>
        <slot></slot>
    </DemoContainer>
    <ViewiAssets />
</body>

</html>

And use this layout in two different pages:

HomePage

<Layout title="Home page">
    <h1>Home page</h1>
</Layout>

PostPage

<Layout title="Post page">
    <h1>Post page</h1>
</Layout>

Routing:

$router->get('/', HomePage::class);
$router->get('/post/{id}', PostPage::class);

Now, if you navigate from one page into another, a Layout component will preserve its state and page content after navigation and the timer will keep running and updating the page each second.

Important

Only top level components are reused and only if next page is also using it.

For example, Layout will is shared because both pages are using it at the top level:

<Layout title="Post page">
    <h1>Post page</h1>
</Layout>

This will not be shared, it is not at the top level, it is just a regular child component:

<html>
    <Layout title="Post page">
        <h1>Post page</h1>
    </Layout>
</html>

Multiple layouts

You can have many sub layouts or even different layout at all.

Sub layouts

You can have BaseLayout and PublicLayout for example:

BaseLayout

<!DOCTYPE html>
<html lang="en">

<head>
    <title>
        $title | Viewi
    </title>
</head>

<body>
    <slot></slot>
    <ViewiAssets />
</body>

</html>

PublicLayout

<BaseLayout title="$title">
    <div id="sidebar">
        <MenuBar />
    </div>
    <DemoContainer>
        <slot></slot>
    </DemoContainer>
</BaseLayout>

In this case both layouts are going to be reused if navigation happens to the page with the same layout PublicLayout.

If you next page uses different sub layout, but the same top level layout BaseLayout, only the BaseLayout layout will be reused.

Different HTML level layout

Layout with html tag and ViewiAssets component is called a top level layout.

Please be aware.

If you use many top level layouts, the content will not be preserved and page refresh will occur from the server due to its environment nature in the browser. Scripts can not be unloaded from the memory, full page refresh is needed.