Edge components
A component is a template for a repeated block with its own parameters: a post card, a button, an error message. You write it once and use it on different pages with different data. The layout from the previous lesson was a component too.
A component with props
Create a post card:
node ace make:view components/post/card{{-- resources/views/components/post/card.edge --}}
<article class="post-card">
<h2>
<a href="{{ route('posts.show', { id: post.id }) }}">{{ post.title }}</a>
</h2>
<p>{{ post.excerpt }}</p>
</article>The post variable comes from outside as a component prop. The file is in the nested post folder, so the tag is called @post.card.
Using the component
{{-- resources/views/pages/posts/index.edge --}}
@layout({ title: 'All posts' })
@each(post in posts)
@!post.card({ post })
@end
@endThe exclamation mark in @!post.card means a tag without content: no closing @end is needed. The page shows each post as a separate card.
The default slot
To pass markup into a component, use a slot. Let us make a notice block:
{{-- resources/views/components/alert.edge --}}
<div class="alert alert-{{ type ?? 'info' }}">
{{{ await $slots.main() }}}
</div>{{-- resources/views/pages/posts/show.edge --}}
@alert({ type: 'warning' })
This post is not published yet. <a href="/posts">Back to the list</a>
@endThe content between the tags goes into $slots.main(), and the type prop picks the CSS class. Without the prop the block gets the class alert-info.
Named slots
Sometimes a component needs several places for markup. They are named with the @slot tag:
{{-- resources/views/components/panel.edge --}}
<section class="panel">
<header>{{{ await $slots.header() }}}</header>
<div>{{{ await $slots.main() }}}</div>
</section>{{-- resources/views/pages/posts/show.edge --}}
@panel()
@slot('header')
Comments
@end
<p>No comments yet.</p>
@endThe text "Comments" ends up in the panel header, and the paragraph in the main part. If a slot may be missing, check for it: @if($slots.header).
Another syntax
Docs and older projects use the @component tag. It does the same thing:
{{-- resources/views/pages/posts/index.edge --}}
@!component('components/post/card', { post })Common mistake
Components are looked up only in resources/views/components/. If you put card.edge into resources/views/partials/, the @card tag fails with an unknown tag error. Use @include for pieces without parameters and keep components in components.