What is the ~E sigil in the Drab tutorial?

Hi,

I’m going through the examples on the drab page. In the ‘chat example’ section, in the code example.

defhandler update_chat(socket, sender) do
  nick = get_store(socket, :nickname, "Anonymous")
  html = ~E"<strong><%= nick %>:</strong> <%= message %><br>" |> safe_to_string()
  broadcast_insert socket, "#chat", :beforeend, html
  set_prop socket, this(sender), value: ""
  broadcast_js socket, "document.querySelector('#chat').scrollTop = 
  document.querySelector('#chat').scrollHeight"`
end  

On the third line, the one with html, a sigil ~E is used. I don’t know what this does, and it doesn’t show up in the elixir docs or in the page source code. Anyone know what this is?

1 Like

That comes from Phoenix HTML package: “Provides ~E sigil with HTML safe EEx syntax inside source files”.

https://hexdocs.pm/phoenix_html/Phoenix.HTML.html#sigil_E/2

7 Likes

It is important to use safe when you build html from the outside source, like inputs. Future versions of Drab will take safe directly, so you’ll not have to add safe_to_string/1.

2 Likes

Trying chat example as well.
Getting
page_commander.ex:13: undefined function safe_to_string/1

Do

import Phoenix.HTML

in the commander, or just call Phoenix.HTML.safe_to_string directly.

1 Like

Tried to call module.function, that gave page_commander.ex:14: undefined function sigil_E/2.
Now,
page_commander.ex:16: undefined function message/0

it’s the 3rd line in

  defhandler update_chat(socket, sender) do
    nick = get_store(socket, :nickname, "Anonymous")
    html = ~E"<strong><%= nick %>:</strong> <%= message %><br>" |> safe_to_string()
1 Like

You need to define message within the function. It’s currently not defined and the program assumes its some undefined function.

What I did was get the message value from the sender.

message = sender["value"] 

Or something similar, I’ll post the actual code when I get the chance.

Yes, I made a mistake when copying the code to the html, will be added soon.
message = sender["value"] is correct.

1 Like

Yes, this works:

  defhandler update_chat(socket, sender) do
    nick = get_store(socket, :nickname, "Anonymous")
    message = sender["value"]
    html = ~E"<strong><%= nick %>:</strong> <%= message %><br>" |> safe_to_string()
...

@grych another issue with chat:

defmodule AppWeb.PageCommander do
  use Drab.Commander #, modules: [Drab.Presence]
  import Phoenix.HTML
  import Drab.Presence

gives error:

** (CompileError) lib/olist_no_brunch_web/commanders/page_commander.ex:4: module Drab.Presence is not loaded and could not be found
    (stdlib) erl_eval.erl:677: :erl_eval.do_apply/6

I have in config:

config :drab, :default_modules, [Drab.Live, Drab.Element, Drab.Waiter, Drab.Modal, Drab.Presence]
config :drab, :presence, id: [store: :nickname, session: :nickname] 
config :drab, :presence, endpoint: AppWeb.Endpoint

and still no luck :((

1 Like

Which version of Drab do you have?

Try to:

  1. remove import Drab.Presence from the commander, it is not needed.
  2. remove Drab.Presence from default modules
  3. do mix clean

You may always take a look on the Drab Examples Page source to find out how it is done.

1 Like

Yes, that page was my reference, but I couldn’t find the difference.
The only 1 I see now is that you are using own module to store data worker(DrabPoc.Presence, []), but the app should work w/o it.
After your instructions had same error.
Removed _build dir, restarted app, and now it works!

version 0.9.1

Oops, this is bad, it shouldn’t be like this.
Compilation of Drab.Presence depends on the config options, this must be an issue. I will try to hunt it down.

@grych debug info: I was done with Chat Example in https://tg.pl/drab and it was working fine.
Then I started adding Presence and got into trouble until removing the build.

1 Like

Thanks for Drab - I am really enjoying it. I wanted to ask if this issue with Drab.Presence had been resolved. I am using 0.10.1 (Phoenix 1.4) and wonder if I have the same problem.

For example, if I create a stock app “my_app” (mix phx.new my_app), and do the following (let me apologize now if I am missing/screwing up a step):

  1. add {:drab, "~> 0.10.1"} to config.exs
  2. mix deps.get
  3. mix drab.install
  4. mix drab.gen.commander Page
  5. add config :drab, :presence, true to config.exs
  6. add Drab.Presence to my supervision tree in lib/my_app/application.ex
  7. add import Drab.Presence to page_commander.ex

I get the error below when I run mix phx.server:

 (CompileError) lib/my_app_web/controllers/page_controller.ex:3: 
module Drab.Presence is not loaded and could not be found

From this point if I rm -rf _build and mix phx.server again, everything recompiles and I get the same error.

Hi there,
Do you still have an issue with this?

1 Like

Yes and no. I did the steps (edited below to be more accurate) and I get the same error. However - this time I did rm -rf _build and then when I restarted the server it recompiled with no error. That works for me!

That said - please let me re-document my steps as I did not record them 100% correctly the first time. I am using Phoenix 1.4, Elixir 1.7.4, Erlang/OTP 21.

  1. mix phx.new my_app --no-ecto
  2. add {:drab, "~0.10.1"} to mix.exs
  3. mix deps.get
  4. mix drab.install
  5. mix drab.gen.commander Page
  6. add config: drab, :presence, true to config.exs
  7. add Drab.Presence to my supervision tree in lib/my_app/application.ex
  8. add import Drab.Presence to page_commander.ex
  9. note that config: Drab, MyAppWeb.Endpoint, otp_app: my_app is in config.exs
  10. run mix phx.server

I deviated from the instructions in the docs in two respects:

  1. The docs say to modify the supervision tree in lib/my_app_web.ex; I’m assuming that where the supervision tree was specified in an older version of Phoenix?

  2. The docs say to make sure that config: Drab, MyAppWeb.Endpoint, otp_app: my_app_web is set, not my_app, which is what was inserted into my file by the generator. I admit I don’t really understand what that is doing. I did modify it to my_app_web and get the same error, for what that is worth.

2 Likes

Thanks for the explanation. I am going to check it!
Thanks.