Amber: Views macro enhancement

Created on 21 May 2018  路  6Comments  路  Source: amberframework/amber

About What?

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.

Why it's necessary?

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>

Is there way better system?

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..

enhancement feature wip

All 6 comments

808

@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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

elorest picture elorest  路  6Comments

elorest picture elorest  路  7Comments

sumwatt picture sumwatt  路  4Comments

faustinoaq picture faustinoaq  路  4Comments

bigforcegun picture bigforcegun  路  3Comments