@Eiji - I’ve finished the toggle. But it does more - does not just switch between two values, but you can specify more than two. Every time it is launched, it changes the value to the next on the list (or first if it reach the list end).
socket |> update(:class, set: ["btn-success", "btn-danger", "btn-primary"], on: "#btn")
Your API looks great!
Did you think about writing JS library with similar API (without socket as first argument)? I think it’s really clear and easy to learn. I can do this too if you don’t have any copyrights restrictions.
@vic,
Drab 0.2.0, just released, is now modular. This means that Drab.Query and Drab.Modal are not obligatory - you may specify the list of modules to use on the Commander:
use Drab.Commander, modules: [Drab.Query]
In your case, when you need to have only basic functions execjs, you’ll use:
user Drab.Commander, modules: []
This will load the Drab.Core (which is neccessary and is always included) only.
There is more: this architecture is open for extending Drab. You may create your own module (for example for react) with corresponding JS template and put it in your project. Let’s make Drab growing!
@grych: I have new idea.
Did you already have implemented events?
You could do something like:
alias Drab.Event
Event.add(:method, [target_name: "target value"], [attr_name: "attr value"], &callback/3)
Event.remove(opts)
# Examples:
Event.remove(callback: &callback/3) # remove all events with specified callback
Event.remove(target: [id: "#my_special_btn"]) # remove all events that affects specified element
# ...
defmodule MyApp.Callbacks.MySpecialBtn do
# maybe GenStage consumer?
def on_delete_btn_class(socket, btn, changes) do
# btn is map/struct for target button - struct from HTML element
# changes is for example: {:deleted, :css, "btn"}
end
end
Event.add(:delete, [class: "btn"], [id: "#my_special_btn"], &MyApp.Callbacks.MySpecialBtn.on_delete_btn_class/3)
Add force: true (default to false) if our target matches another selector
alias Grab.Event
Event.add(:update, [], [class: "btn"], &callback/3, force: true)
# add event for all updates on elements with class: btn
update(socket, style: "font-size", set: 6, unit: :px, on: "#button")
so if element with #btn has class btn and we set force: true then we should start callback
It is pretty high security, has to be renewed every month, but there are automation things galore for that for every web server or even just to add as a cron job.
/me is lazy and just uses a cron job one to update nginx certs.
@grych I like both the API and the idea very much. It’s like the RJS templates from good 'ol days Rails 2.x, but on steroids thanks to persistent nature of Phoenix sockets.
One must think of limitations and downsides of going with this approach before choosing it over say API + React, however I think it’ll do well for most applications. And I guess you can throw in some JavaScript where it does not do good enough job.
I usually deal with a lot of forms, and the dynamic bits on these forms can be like inputs that format say phone number, or postcode as you type. I think writing those as tiny react components would be great fit. Drab would still treat those as normal input when collecting the data server-side.
On a positive side, I am mostly thinking about the code you no longer have to write. Less code == less bugs.
On a negative side, I see that the coupling between back-end event handlers and UI will make stuff like UI upgrades slightly more complex. I also have a hunch you can easily write really bad spaghetti, unmaintainable code this way. I remember the problems we had with RJS and how eventually the Rails community decided to abandon the idea.
Either way, I will give it a shot really soon. The current front-end situation is ridiculous. This is a step back, but a tactical retreat rather than escape :).
@Eiji,
thanks for the idea! I need to think about it. It is quite easy to implement it on the server side, but to be consistent it should work on the client side as well. So event should be launched after change in javascript as well.
@hubertlepicki,
the big picture is to keep everything on the server side. I started with DOM interfaces, Drab.Query module simple translates Elixir functions (select, update etc) to corresponding jQuery methods and executes it on the client side.
Why not to create a similar module for, for example, React? So you could build the whole interface in Elixir.
Ops, sorry my fault. I’ve changed the server over the weekend and have an issues with elixir/erlang installed from the package (Debian) - memory is leaking like hell. I am installing it from the source now. Please check in 1/2 hour, should be working again.
This is what concerns me as well.
In theory, its reliability should be the same as Phoenix/Websockets, but you never know. This software still needs a lot of work and test. Anyway, enjoy!