Lol, well the PR has nothing to do with 1.3 stuff, that is just release stuff. Calling Code.ensure_compiled
or whatever it was returns {:error, :embedded}
when the program is mix release
d, thus crash only on release. ^.^
OK, I will do smaller release than I planned especially for you
Anyway, it will contain P13 fix.
Lol, thanks! It is quite a blocking bug considering mix release
fails otherwise. ^.^;
Thanks for your both answers !
Then I will keep some templates with plain html, thats ok (still I think that would be great to manage Haml !
I didnāt get at first Drabās ability to call functions directly from js ; thatās cool !
My plan is to place some assigns in an html template, play with it with js, then push some changes to repo and load fresh new assign in the template (without reloading the whole page). I like Drabās approach to avoid Ajax, and tried to use put_store and storage location on load. My point is I canāt find how to make that work :
- My commander doesnāt look to see my controllerās assigns (storage location remains empty)
- I manage to query Ecto directly from the commander, but get an āAssign not found in Drab EEx templateā (and i am not sure that querying Ecto should be done by Drabā¦)
Any suggestion ?
Txs !
Are you using peek/2 to retrieve the assign value?
About Ecto: Assign not found doesnāt have anything with Ecto. You can use Ecto queries anywhere, of course also in the Drab commander.
Please share a part of your code, we will find out how to manage it.
Here it is (I simplified a bit) :
My membershipās controller has a test method :
def test(conn, _params) do
memberships =
query_user(conn, _params)
|> Repo.all
conn
|> assign(:memberships, memberships)
|> render "test.html"
end
The membershipās commander :
def page_loaded(socket) do
initial = peek(socket, :memberships) # Load assign
put_store(socket, :memberships, initial) # Store assign in localStorage
current = get_store(socket, :memberships) # Retrieve assign from localStorage
IO.inspect(current)
end
I do not render the @memberships in the template, but use some js afterward to check localStorage content. Still no magic as I keep getting an empty localStorage and a :
Assign @memberships not found in Drab EEx template
Does it mean the assign must be rendered ? Where am I wrong ?
Txs
Store (and session) is the different entity than assigns.
With Drab, you use assigns normally, while rendering template from the controller. Then, you may poke
and peek
assigns live, from the commander.
All is explain on the demo/tutorial page, here Drab: Server Side User Interface Access
Ok, I realized I misunderstood when to use Drab (I was thinking Drabās store is accessible from js thanks to localStorage By default, Drab Store is kept in browser Local Storage.
, but cant find how).
I turned tmyself to PhoenixGon to load assigns in js, then I will use Drab to trigger updates in my templates.
Thanks again for your help
Drab Store is kept in the local store, or memory (as configured) and it is available only from Drab. Well, in theory you could decrypt it in JS (values are signed with Phoenix.Token), but the intention is to keep all the code on the server side.
@grych Drab is a really cool library! Thanks for making it. Lately Iāve been feeling like building SPAās presents a lot of unnecessary complexity for so little extra benefit. Your library can fill the gap.
I havenāt dug too deeply into Drab (looked through the README and hexdocs) but have a question. I sometimes use Postgres listen/notify to get real time updates when data changes. Iāve used the Boltun library to manage listen/notify callbacks and am wondering if it is possible to trigger a commander function from another module on the server (e.g. from my Boltun callback). Iād like to update a table of records on all connected clients via drab when the database is changed. Sorry if this is documented somewhere and I missed it
You just need to broadcast the update to all connected browsers. You can do it from any part of your application, as broadcasting functions do not need a socket to send the updates.
You may use Drab.Element.broadcast_prop or the similar function from Drab.Query or even simple Drab.Core.broadcast_js
See
https://hexdocs.pm/drab/Drab.Commander.html#module-broadcasting-options
https://hexdocs.pm/drab/Drab.Core.html#broadcast_js/3
for the broadcasting options.
BTW docs about broadcasting should be updated, not easy to find it.
BTW2 do you think I should make a broadcast versions of Drab.Element.set_attr, set_style etc? For now there is only broadcasting version of set_prop.
Iām having trouble getting it to work. I have a controller (ScrivWeb.CaseController) that is using Drab.Controller. I also have a CaseCommander module. I have a couple commander functions that work fine so I know it is setup correctly. The issue arises when in CaseController I call
Drab.Core.broadcast_js(Drab.Core.same_controller(ScrivWeb.CaseController), "alert('Broadcased')")
Iām calling it after the create action creates a new case in the controller to test that I can send a message to all connected clients. I get the following error:
[error] #PID<0.936.0> running ScrivWeb.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /cases
** (exit) an exception was raised:
** (ArgumentError) argument error
(stdlib) :ets.lookup(ScrivWeb.PubSub, :broadcast)
(phoenix_pubsub) lib/phoenix/pubsub.ex:288: Phoenix.PubSub.call/3
(drab) lib/drab/core.ex:248: Drab.Core.broadcast_js/3
(scriv) lib/scriv_web/controllers/case_controller.ex:30: ScrivWeb.CaseController.create/2
(scriv) lib/scriv_web/controllers/case_controller.ex:1: ScrivWeb.CaseController.action/2
(scriv) lib/scriv_web/controllers/case_controller.ex:1: ScrivWeb.CaseController.phoenix_controller_pipeline/2
(scriv) lib/scriv_web/endpoint.ex:1: ScrivWeb.Endpoint.instrument/4
(phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
(scriv) lib/scriv_web/endpoint.ex:1: ScrivWeb.Endpoint.plug_builder_call/2
(scriv) lib/plug/debugger.ex:99: ScrivWeb.Endpoint."call (overridable 3)"/2
(scriv) lib/scriv_web/endpoint.ex:1: ScrivWeb.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /Users/ryanswapp/Documents/code/elixir/test-apps/scriv/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
Any idea as to what I may be doing wrong?
Also, is it possible to only send a message to clients connected to the page rendered by the index action instead of all clients connected to a page rendered by any action in the CaseController?
Thanks for your help
Edit: I realized that I need to pass the socket struct to the broadcast_js function rather than the string returned from same_controller(). Iām guessing that socket struct is stored somewhere I can access so Iāll look around the code to find out where you are putting it.
Does this command work from IEx, when you have a page displayed in the browser?
:ets.lookup(ScrivWeb.PubSub, :broadcast)
looks nasty here.
For broadcasting, you donāt need a socket. Take a look at the presence example:
https://tg.pl/drab#presence
@ryanswapp , could you please try to get https://github.com/grych/drab-example and run:
Drab.Core.broadcast_js Drab.Core.same_path("/"), "alert('a')"
on that?
So we would know if there is an issue with the environment or with the setup.
No it does not
iex(2)> :ets.lookup(ScrivWeb.PubSub, :broadcast)
** (ArgumentError) argument error
(stdlib) :ets.lookup(ScrivWeb.PubSub, :broadcast)
Drab.Core.broadcast_js Drab.Core.same_path("/"), "alert('a')"
This works in your example. I cloned it and everything worked fine. Iām not sure why, but perhaps there is an issue with Phoenix 1.3 (Iām on Drab 0.5 and I saw an issue stating 1.3 wasnāt supported)? My test app is on 1.3.
With regard to setup, Iāve followed the README instructions exactly and just double checked to make sure everything was there. I set it up to do the uppercase example and it all works fine. The code fails, however, when I try to execute stuff in iex.
Just upgraded to master branch and it works! Thanks