Unexpected token : end

I do my first project, with
Erlang/OTP 22 [erts-10.5.6] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [hipe]
Elixir 1.9.1 (compiled with Erlang/OTP 21)

First I created user in lib/nage/accounts/user.ex

defmodule Nage.Accounts.User do
  defstruct [:id, :username, :name]
end

I tested in elixir struct that’s good no problem

Second I create Accounts in lib/nage/accounts.ex

defmodule Nage.Accounts do
  @moduledoc """
  dalam kontex accounts
  """
  alias Nage.Accounts.User

  def list_users do
    [
      %User{id: "1", username: "syakir", name: "ahmad syakir"},
      %User{id: "2", username: "mahmud", name: "mahmud syakir"},
      %User{id: "3", username: "syukri", name: "syukri adnan"}
    ]
  end

  def get_user(id) do
    Enum.find(list_users(), fn map -> map.id == id end)
  end

  def get_user_by(params) do
    Enum.find(list_users(), fn map ->
      Enum.all?(params, fn {key, val} -> Map.get(map, key) == val end)
    end)
  end
end

I tested in elixir struct that’s good no problem

third I created router in lib/nage_web/router.ex

  scope "/", NageWeb do
    pipe_through :browser

    get "/", PageController, :index
    get "/users", UserController, :index
    get "/users/:id", UserController, :show
  end

fouth I created Controller in lib/nage_web/controllers/user_controller.ex

defmodule NageWeb.UserControler do
  use NageWeb, :controller

  alias Nage.Accounts

  def index(conn, _params) do
    users = Accounts.list_users()
    render(conn, "index.html", users: users)
  end

end

fifth I created view in lib/nage_web/views/user_view.ex

defmodule NageWeb.UserView do
  use NageWeb, :view

  alias Nage.Accounts

  def firs_name(%Nage.Accounts.User{name: name}) do
    name
    |> String.split("")
    |> Enum.at(0)

  end
end

sixth I created template in lib/nage_web/templates/user/index.html.eex

<h1>List of Users</h1>

<table>
<%= for user <- @users do%>
<tr>
    <td><b><%= first_name(user)%></b>(<%=user.id%>)</td>
    <td><%= link"View", to: Routes.user_path(@conn, :show, user.id)%></td>
</tr>
<% end %>
</table>

when I run Mix phx.server I got error like these

Compilation error in file lib/nage_web/views/user_view.ex ==
** (SyntaxError) lib/nage_web/templates/user/index.html.eex:9: unexpected token: end
(eex) lib/eex/compiler.ex:101: EEx.Compiler.generate_buffer/4
(eex) lib/eex/compiler.ex:54: EEx.Compiler.generate_buffer/4
(phoenix) lib/phoenix/template.ex:354: Phoenix.Template.compile/3
(phoenix) lib/phoenix/template.ex:165: anonymous fn/4 in Phoenix.Template.“MACRO-before_compile”/2
(elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix) expanding macro: Phoenix.Template.before_compile/1
lib/nage_web/views/user_view.ex:1: NageWeb.UserView (module)
(elixir) lib/kernel/parallel_compiler.ex:229: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

<%= for user <- @users do%> 
    <%= first_name(user)%> (<%=user.id%>) 
    <%= link"View", to: Routes.user_path(@conn, :show, user.id)%>
<% end %>

You have put the <% end %> right next to the for loop. The contents should be between the for and the end

Is that a typo?

The error is here…

<%= first_name(user)%>

and I think it’s because You made this typo… def firs_name

Sidenote: for this kind of filtering we have Kernel.match?/2 which is way more expressive:

Enum.find(list_users(), &match?(%{id: ^id}, &1))
2 Likes

I try to fix the problem, with template

List User

user <- @users do
first_name(user)(user.id) link"View", to: Routes.user_path(@conn, :show, user.id)

with view like this
defmodule NageWeb.UserView do
use NageWeb, :view

alias Nage.Accounts

def firs_name(%Accounts.User{name: name}) do
name
|> String.split("")
|> Enum.at(0)

end
end

user_controller like this
defmodule NageWeb.UserControler do
use NageWeb, :controller

alias Nage.Accounts

def index(conn, _params) do
users = Accounts.list_users()
render(conn, “index.html”, users: users)
end

end

and router like this

defmodule NageWeb.Router do
use NageWeb, :router

pipeline :browser do
plug :accepts, [“html”]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end

pipeline :api do
plug :accepts, [“json”]
end

scope “/”, NageWeb do
pipe_through :browser

get "/", PageController, :index
get "/users", UserController, :indexs

end

Other scopes may use custom stacks.

scope “/api”, NageWeb do

pipe_through :api

end

end

I am not an expert in rendering templates in general and EEx engine in particular, but I believe spaces between tags and content are mandatory.

Try to carefully put spaces distinguishing all the tags, like <%= user.id %> etc.

It got me too (In EEx you don't simply omit the space in: ... do%>).