Views dalam arsitektur MVC bertanggung jawab untuk menampilkan data kepada pengguna. NexaUI menggunakan sistem template yang powerful namun sederhana untuk memisahkan logika presentasi dari logika bisnis, memungkinkan pengembangan antarmuka yang fleksibel dan mudah dipelihara.
Template di NexaUI disimpan dalam direktori templates/
dan diorganisir berdasarkan
area fungsional atau jenis device:
templates/
├── 404.html # Error page
├── dashboard/ # Admin dashboard templates
│ ├── index.html
│ ├── users.html
│ └── settings.html
├── index.html # Main layout
├── mobile/ # Mobile-specific templates
│ ├── index.html
│ └── article.html
├── tablet/ # Tablet-specific templates
│ ├── index.html
│ └── article.html
└── theme/ # Theme components
├── header.html
├── footer.html
├── menu.html
└── sidebar.html
Template NexaUI menggunakan sintaks sederhana dengan placeholder dalam kurung kurawal {variable}
.
Berikut adalah contoh template dasar:
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title}</title>
<link rel="stylesheet" href="http://www.tatiye.net/assets/css/style.css">
</head>
<body>
<div class="container">
<h1>{title}</h1>
<p>{content}</p>
<!-- Conditional rendering -->
<!-- IF logged_in -->
<p>Welcome, {user_name}!</p>
<!-- ELSE -->
<p>Please <a href="http://www.tatiye.net/login">login</a> to continue.</p>
<!-- END IF -->
</div>
</body>
</html>
NexaUI menggunakan template engine yang mendukung berbagai fitur:
Variabel ditampilkan menggunakan sintaks {variable}
:
<h1>{title}</h1>
<p>{description}</p>
<!-- Nested properties -->
<p>Author: {article.author.name}</p>
<!-- With default value -->
<p>{comment|default:"No comments yet"}</p>
<!-- With filters -->
<p>Posted on: {created_at|date:"Y-m-d H:i"}</p>
<p>{content|truncate:100}</p>
Blok kondisional memungkinkan rendering bersyarat:
<!-- Simple condition -->
<!-- IF logged_in -->
<p>Welcome back!</p>
<!-- ELSE -->
<p>Please login.</p>
<!-- END IF -->
<!-- Multiple conditions -->
<!-- IF role == "admin" -->
<a href="http://www.tatiye.net/admin">Admin Panel</a>
<!-- ELSEIF role == "editor" -->
<a href="http://www.tatiye.net/editor">Editor Dashboard</a>
<!-- ELSE -->
<a href="http://www.tatiye.net/profile">Your Profile</a>
<!-- END IF -->
<!-- Comparison operators -->
<!-- IF items_count > 0 -->
<p>You have {items_count} items in your cart.</p>
<!-- ELSE -->
<p>Your cart is empty.</p>
<!-- END IF -->
Loop digunakan untuk mengiterasi array atau koleksi:
<!-- Simple loop -->
<ul>
<!-- LOOP users -->
<li>{name} ({email})</li>
<!-- END LOOP -->
</ul>
<!-- Loop with index -->
<table>
<!-- LOOP products -->
<tr class="odd">
<td>{_index + 1}</td>
<td>{name}</td>
<td>{price|currency}</td>
</tr>
<!-- END LOOP -->
</table>
<!-- Empty check -->
<!-- LOOP comments -->
<div class="comment">
<h4>{author}</h4>
<p>{text}</p>
</div>
<!-- EMPTY -->
<p>No comments yet.</p>
<!-- END LOOP -->
Include digunakan untuk menyertakan template lain:
<!-- Include header template -->
{include/theme/header}
<!-- Main content -->
<div class="content">
<h1>{title}</h1>
<p>{content}</p>
</div>
<!-- Include footer template -->
{include/theme/footer}
<!-- Include with variables -->
{include/theme/sidebar sidebar_title="Navigation" active_item="home"}
NexaUI mendukung sistem layout untuk menghindari duplikasi kode. Layout adalah template yang berisi struktur umum halaman dengan placeholder untuk konten spesifik.
Layout biasanya disimpan di templates/layouts/
:
<!-- templates/layouts/default.html -->
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title} - NexaUI</title>
<link rel="stylesheet" href="http://www.tatiye.net/assets/css/style.css">
<!-- BLOCK head -->
<!-- END BLOCK -->
</head>
<body>
<header>
{include/theme/header}
</header>
<main>
<!-- BLOCK content -->
<p>Default content</p>
<!-- END BLOCK -->
</main>
<footer>
{include/theme/footer}
</footer>
<script src="http://www.tatiye.net/assets/js/desktop.combined.min.js"></script>
<!-- BLOCK scripts -->
<!-- END BLOCK -->
</body>
</html>
Template dapat menggunakan layout dan mengisi blok konten:
<!-- templates/articles/show.html -->
{extends/layouts/default}
<!-- BLOCK head -->
<meta property="og:title" content="{article.title}">
<meta property="og:description" content="{article.excerpt}">
<!-- END BLOCK -->
<!-- BLOCK content -->
<article>
<h1>{article.title}</h1>
<div class="meta">
By {article.author.name} on {article.published_at|date:"F j, Y"}
</div>
<div class="content">
{article.content}
</div>
</article>
<section class="comments">
<h2>Comments ({article.comments|count})</h2>
<!-- LOOP article.comments -->
<div class="comment">
<h4>{author}</h4>
<p>{text}</p>
</div>
<!-- EMPTY -->
<p>No comments yet.</p>
<!-- END LOOP -->
</section>
<!-- END BLOCK -->
<!-- BLOCK scripts -->
<script src="http://www.tatiye.net/assets/js/comments.js"></script>
<!-- END BLOCK -->
Di controller, gunakan method render()
untuk menampilkan template dengan data:
public function show(int $id): void
{
$article = $this->articleRepository->find($id);
if (!$article) {
$this->notFound();
return;
}
$comments = $this->commentRepository->findByArticle($id);
$data = [
'title' => $article->getTitle(),
'article' => $article,
'comments' => $comments
];
$this->render('articles/show', $data);
}
Anda juga dapat menentukan layout yang berbeda:
// Render dengan layout tertentu
$this->render('articles/show', $data, 'layouts/sidebar');
// Render tanpa layout
$this->render('articles/show', $data, null);
NexaUI menyediakan beberapa helper untuk digunakan dalam template:
<!-- Generate URL -->
<a href="http://www.tatiye.net/articles">All Articles</a>
<a href="http://www.tatiye.net/articles/123">View Article</a>
<!-- With parameters -->
<a href="{link/articles?category=tech&sort=newest}">Tech Articles</a>
<!-- Asset URL -->
<img src="http://www.tatiye.net/assets/images/logo.png" alt="Logo">
<link rel="stylesheet" href="http://www.tatiye.net/assets/css/style.css">
<!-- CSRF token -->
<form method="post" action="http://www.tatiye.net/articles/store">
{csrf_field}
<!-- Input with old value -->
<input type="text" name="title" value="{old.title}" placeholder="Title">
<!-- Error display -->
<!-- IF errors.title -->
<span class="error">{errors.title}</span>
<!-- END IF -->
<button type="submit">Save</button>
</form>
<!-- Date formatting -->
<p>Published: {article.published_at|date:"F j, Y"}</p>
<!-- Text formatting -->
<p>{article.excerpt|truncate:100}</p>
<p>{article.content|nl2br}</p>
<!-- Number formatting -->
<p>Price: {product.price|currency}</p>
<p>Rating: {product.rating|number_format:1}</p>
<!-- HTML escaping -->
<p>{user_input|escape}</p>
<!-- Custom filter -->
<p>{user.role|translate}</p>
NexaUI mendukung template yang berbeda untuk device yang berbeda:
// Di controller
public function index(): void
{
$articles = $this->articleRepository->findLatest(10);
$data = ['articles' => $articles];
// Render template berdasarkan device
if ($this->isMobile()) {
$this->render('mobile/articles/index', $data);
} elseif ($this->isTablet()) {
$this->render('tablet/articles/index', $data);
} else {
$this->render('articles/index', $data);
}
}
Atau Anda dapat menggunakan deteksi otomatis:
// Otomatis memilih template berdasarkan device
$this->renderResponsive('articles/index', $data);
Untuk kode yang digunakan kembali, Anda dapat membuat partial atau komponen:
<!-- templates/partials/article_card.html -->
<div class="article-card">
<h3><a href="{link/articles/{id}}">{title}</a></h3>
<div class="meta">By {author.name} on {published_at|date:"F j, Y"}</div>
<p>{excerpt|truncate:150}</p>
<a href="{link/articles/{id}}" class="read-more">Read more</a>
</div>
<!-- Using the partial -->
<div class="articles">
<!-- LOOP articles -->
{include/partials/article_card}
<!-- END LOOP -->
</div>
NexaUI juga mendukung komponen yang lebih dinamis:
<!-- Using a component -->
{component/NexaPagination total=100 current=5 per_page=10}
<!-- Using a component with custom template -->
{component/NexaAvatar user=current_user size="large" template="theme/custom_avatar"}
Komponen didefinisikan sebagai class PHP:
// system/components/NexaPagination.php
namespace App\System\Components;
class NexaPagination
{
public function render(array $params): string
{
$total = $params['total'] ?? 0;
$current = $params['current'] ?? 1;
$perPage = $params['per_page'] ?? 10;
// Calculate pagination
$totalPages = ceil($total / $perPage);
// Generate HTML
$html = '';
// ... pagination logic
$html .= '';
return $html;
}
}
resource/action.html
(contoh: articles/show.html
).