I think Amber's view system need to improvement for flexible blocks such as Rails content_for - yield ( Kemal already have that feature ), for the better example Laravel's Blade template engine's section-yield system.
That system gives you flexibility, for example you have a template and you have components attached to layout, you want these components to serve different content on the different pages, like home page and post page
Or you want to add sources inside which template needs which sources, like lets imagine you are working on a cryptocurrency website and for homepage you have heavy javascript file which is triggered by onload and fetching currency on different service every 10 seconds, and you dont want that javascript file to load every page. so in that system you only need create a block on homepage template and yield it on layout.
home/index.ecr
<% content_for "title" do %> my homepage title <% end %>
<%= render(partial: "partials/header.ecr") %>
<div class="homepage">...</div>
<%= render(partial: "partials/footer.ecr") %>
<% content_for "footer_scripts" do %>
<script type="application/javascript" src="assets/myheavyjavascriptfile.js"></script>
<% end %>
layouts/app.ecr
<html>
<head>
[here is some meta and css loads]
<title><%= yield_for "title" %></title>
</head>
<body>
<div class="container">
<%= content %>
</div>
[here is common js loads]
<%= yield_for "footer_scripts" %> # here is content_for block which is defined at homepage.ecr.
</body>
</html>
Yes! there is better templating system called _Blade_, that serve way way better templating in my opinion, for example, you can extend layout on your template, and pass data to sections which you want to use.
. (dot) characters replaced as / (slash) characters, because typing dot easy than slash
homepage.php
@extends('layouts.app')
@section('title', 'my homepage title')
@include('partials.header')
@section('content')
<div class="homepage">...</div>
@endsection
@include('partials.footer')
@section('footer_scripts')
<script type="application/javascript" src="assets/myheavyjavascriptfile.js"></script>
@endsection
layouts/app.php
<html>
<head>
[here is some meta and css loads]
<title>App Name - @yield('title')</title>
</head>
<body>
<div class="container">
@yield('content')
</div>
[here is common js loads]
@yield('footer_scripts')
</body>
</html>
So on..
@yorci What about just setting it directly with either a method or variable? This is how content is being set.
For example, Change your application layout:
<html>
<head>
<title><%= title %></title>
</head>
<body>
<div class="container">
<%= content %>
</div>
<%= footer %>
</body>
</html>
And then in the controllers/application_controller.cr you set your default:
class ApplicationController < Amber::Controller::Base
...
private def title
"Blog using Amber"
end
private def footer
# render default footer. Could be a partial.
""
end
end
And then in your controller, you can override it:
class HomeController < ApplicationController
def index
render "index.slang"
end
private def title
"My Home Page"
end
end
@drujensen Hi, im always on the side of separation of frontend and backend, if i will try to do my example in your way, i have to put my javascript code into controller, but what if frontend dev. wants to do some changes? he/she has to do it in backend, so its not simplifies the developer's side, especially in a large-scale or growth potential project.
If you want to set the title in the template instead of the controller, here is another option.
In your controllers/application_controller.cr, add a property:
class ApplicationController < Amber::Controller::Base
property title : String?
...
end
In your views/layouts/application.ecr:
<html>
<head>
<title><%= title || "Blog with Amber" %></title>
</head>
<body>
<div class="container">
<%= content %>
</div>
</body>
</html>
Now in your views/home/index.ecr, set the title:
<% title = "My Home Page" %>
wdyt? This seems like a clean solution and doesn't require yield
@drujensen looks cool, i will try that in next project.
I'm going to close this for now. Let me know if this solution suffices or if you feel an additional set of macros is needed.