What does your ideal version of Phoenix look like - fork - template engine

I love almost every part of Phoenix, except one: the template engine.

As a .NET developer, I have suffered in my skin the difference between template engines. In .NET MVC world we have the Razor that uses a more optimized and friendly way to write server code into templates. With a simple @, you can create any HTML element, use helpers and data model. It would be awesome to have a similar engine on the Phoenix framework.

I’m wondering how this is different to EEx though besides the <%= %> vs @ syntax?

Avoid <%= %> syntax is a good improvement (one character vs five), because it is less intrusive, and more HTML friendly. If other people are doing front-end in your project (designers or front-end developers), it’s better because it does not interfere so much with the real HTML. And if you are working alone or doing front and back-end is less error prone than the current syntax.

For example, this piece of code:

<h1>Users</h1>

<%= link "New User", to: new_user_path(@conn, :index) %>

<ul>
  <%= for user <- @users do %>
    <li><%= user.name %> (<%= user.age %>)</li>
  <% end %>
</ul>

Could be something shorter and easy to read if were:

<h1>Users</h1>

@link "New User", to: new_user_path(@conn, :index)

<ul>
    @for user <- @users do 
        <li>@user.name  (@user.age)</li>
    end 
</ul>

Furthermore in the last version of Razor you can use tag helpers and you can write back-end code by using special HTML tags.

For example:

@Html.TextBoxFor(m=>m.FirstName, new { @class = "form-control", placeholder=”add a first name”})

Would be:
<input asp-for="FirstName" placeholder=”add a first name” class="form-control" />

1 Like

Coming from php → rails → phoenix I’ve always used the <%= <?= etc syntax so its interesting to see a different one. I’ve never used it so no opinion on what is better to work on but have you considered trying to reimplement it in elixir?

it’s better because it does not interfere so much with the real HTML

To me it looks like it interferes about the same both ways just a difference in the characters. What do you see as it interfering less?

Furthermore in the last version of Razor you can use tag helpers and you can write back-end code by using special HTML tags.

Sorry don’t know Razor, what does that input do differently than a normal one that involves backend code? Could you explain how it works?

I have worked many years with ASP .NET so maybe my opinion is a little bit conditioned.

HTML is a markup language that uses <> symbols a lot. If you are using the same characters in your template engine, in some way you are obfuscating your HTML. When the template is short and clean, it does not matter. But some times the views are very complex and are far cleaner and easy to read if you avoid using <%= to write your Elixir (Ruby or PHP) code.

Here is a bigger example from ASP .NET Core docs:

For me, it’s much cleaner than Phoenix templates. It’s much more easy to see where is the server code and where the HTML code.

But with ASP .NET Core (the last version) you can also use tag helpers that are much more HTML friendly. The same example with tag helpers:

The asp-* tags are the server code, and they do not interfere with HTML code, so it’s much cleaner and easy to read.

3 Likes

Thank you for the reply. What function do the asp-for attributes provide?

The example is a simple one, so it’s just an HTML form. Some tags are used for defining the controller and action to call (similar to form_for in Phoenix), other tags bind the model with their inputs (useful when you are editing data and it has to be preloaded) and others provide some client validation.

Older Microsoft ASP.NET tech is also using <% %> but they moved to using @ when Razor templating was created. Company I currently work for also uses Razor heavily, but C# is quite different language and I’m not quite sure how well templating would work without end marker like %> in EEx. Might not be even possible.

One thing I really hate about ASP.NET’s Razor is unintentional white space. I’m just started learning Elixir and Phoenix and I think it has the same problem. Working with React it’s really great that it doesn’t add any white space between HTML elements by default. You have to explicitly add white space if you need it. So many hours that our company has wasted fixing small UI inconsistencies because Razor doesn’t remove white space between HTML elements.

If EEx suffers from this same problem, it would be great to have an mode where white space was stripped between HTML elements and you would have to explicitly add white space.

Think I got it so

<input asp-for="ConfirmPassword" class="form-control">

is the equivalent of

<%= text_input f, :confirm_password, class: "form-control" %>

That does look quite nice.

Why using a lambda, the new keyword, multiple brackets and that @ symbol is supposed to be cleaner? That’s something you won’t see outside of the ASP.NET world. EEx is simple, just like pretty much any other template engine. I came from the Microsoft lands too and I feel your pain, but have in mind that Phoenix took a few ideas from Ruby on Rails, not from ASP.NET.

I do prefer developer friendly. This is indeed much more cleaner, probably too much, and the purpose template engines shouldn’t be abstracting complexity away with fancy directives / attributes or making your code more integrated with your HTML, but being concise about what you’re trying to achieve. Overall it’s a matter of taste.

You can build your own HTML minifier in Elixir, or you can parse the templates before developing your app to production with tools like Gulp, which it’s a bit weird, but it’s another option if you’re not comfortable with Elixir (ASP.NET has WebMarkupMin). However I must say that minifying the HTML is not a big deal as it won’t affect performance, unless your hosting provider has limited bandwidth, it doesn’t matter.

HTML minimizers usually just removes extra white space. So three spaces are changed to one etc. I’m not talking about that. I’m talking that white space effecting layout in browser. Let’s say you have this

   <div>
      <span>foo</span>
      <span>bar</span>
   </div>

it’s not same as <div><span>foo</span><span>bar</span></div>, first one has white space between foo and bar when you view it in browser. But in React’s JSX/TSX they are the same. To add white space in React you need to use {" "}

So no minimizer will ever fix this problem. Its support has to be added to template it self and you need some way of defining white space you want.

Microsoft’s Razor format updates have also broken our layout so many times because updated formatting didn’t take account white space that was added. Well broken might be a too strong word, but changed how our layout is drawn in browser by adding white space when there was none.

With templating that keeps white space between HTML you have to do hacks like minus margin if you want to keep your template readable. Maybe be our company just cares too about our site looking consistent, but this has been a big issue for us.

1 Like

That’S not a problem of templating engines though. It’s simply how html/css interacts with whitespaces.

The way forms are defined is pretty similar in Razor and EEX. You need a lambda or a function, maybe some CSS classes etc. But you only need a @ in Razor. For me, it’s a big deal. Also when you are adding strings from the model. In EEX it’s a little verbose.

This some times depends on the team. I have worked with people in charge of build things only with HTML and CSS. They didn’t know anything about C#, lambdas or models. With a lot of brackets, lambdas and other non-HTML things they had some problems. But it’s true that you have to know a lot of special directives and it could be hard.

Anyway, I agree with you. It is only a matter of taste, and I know that my request could be weird for Ruby developers.

Yes but React has fixed it in template level and I can’t see why other template engines couldn’t do the same.

I’m not sure if that’s something “fixable”. As soon as you want to have <pre> tags to e.g. render code examples you need whitespace. Also if you’d use phoenix_html helper functions instead of eex templating you’d probably get to something quite similar to jsx (without whitespace).

By removing only white space that is between HTML elements like React does. Text inside <pre> isn’t effected or white space inside foo bar in this <span>foo bar</span>. React JSX templates are proof that it’s “fixable” and works really well.

Edit: Here is how JSX does it https://www.javascriptstuff.com/how-whitespace-works-in-jsx/

JSX does remove new lines and leading and trailing white space. That might be problem if you want new lines in your text. React way is to put literal JavaScript string inside template when you need to preserve white space and new lines. So template needs to have support to preserve white space when need arises.

Just as a suggestion, if you could try to refrain from posting pictures of text it would be awesome, I’m often in a gui-less terminal and having to bring up the post on my phone just to realize the picture was text that could have been included in the post itself wastes a lot of time, plus you can’t highlight it, search for it, etc… ^.^;

EEX isn’t an html template language, it’s a text template language, and removing text that was explicitly put in the file would be very very bad for a variety of formats, even in HTML whitespace is very important, not just in <pre> tags but in a variety of other areas depending on CSS and javascript and all. Just casually wiping whitespace is pretty bad.

If you are wanting something more HTML-specific for templating then there are alternative template engines (and you can mix and match all you want too), like you might like:

Which looks like:

doctype html
html
  head
    meta name="keywords" description="Slime"
    title = site_title
    javascript:
      alert('Slime supports embedded javascript!');
  body
    #id.class
      ul
        = Enum.map [1, 2], fn x ->
          li = x

It keeps proper HTML, it uses selector tags to define elements, it uses = to delinate Elixir calls, etc… etc… It’s always looked interesting to me, but I’m too used to looking at html itself. ^.^

There is also django-like template and pug-like templates and more for elixir/phoenix as well, and it’s not hard to create your own either.


As for @ as a trigger key, that seems to only work for single line expressions, giving no control over how to handle output wrapping afterwards or how to handle multi-expressions or bindings or so? I prefer beginning and end delimiters, though I could see @(...) being useful.

3 Likes

You are right. I thought it was a good example, but I don’t know why ASP .NET Core team put it into an image.

In Razor you can use multiline expressions with brackets @{...}. If you are using conditionals, for example, you have to use something like this:

@if(somethingTrue) {
<p>Its true</p>
}

What about multi-expressions though?