Remote controlled frontend framework for Phoenix.
As a preparation to 0.8.0, this release contains fundamental change in Drab.Live
behaviour. It
removes all the engine limitations, and makes a big change on how it treats @conn
assign.
Please report any found issues with this release.
@conn
caseBecause sometimes it is huge, @conn
is treated in the special way - it is trimmed to contain only
essential fields. By default it is :private => :phoenix_endpoint
, but you may configure it.
config :drab, :live_conn_pass_through, %{
assigns: %{
users: true
},
private: %{
phoenix_endpoint: true
}
}
See Drab.Live
documentation for more details on this case.
:templates_path
config must be under priv/
If you are using :templates_path
config, and your templates are not under the priv/
directory,
you'll have to move them. Solved #105.
This release finally contains all the features of Shared Commanders.
If you are using drab-commander
attribute, the requests coming from the shared commander updates stuff only under this tag.
<div drab-commander="DrabTestApp.Shared1Commander">
<div><%= @assign1 %></div>
<button drab-click="button_clicked">Shared 1</button>
</div>
<div drab-commander="DrabTestApp.Shared1Commander">
<div><%= @assign1 %></div>
<button drab-click="button_clicked">Shared 2</button>
</div>
defhandler button_clicked(socket, sender) do
poke socket, assign1: "changed"
end
This will update only the div with @assign1
in the same <div drab-commander>
as the button. See new demo example.
Callbacks now works in the Shared Commanders.
drab-id
attribute now is generated with the counter, instead of UUIDThis means you are now able to use this/1
and this_commander/1
with the broadcasting functions.
Forces user to reload the page in case the Drab JS library is changed.
This release fixes new, better bug introduced in 0.7.2
This bug was introduced in 0.7.2, after moving update of assigns cache to the connect token.
Updated the applications list in mix.exs
Phoenix.Channel
Set the list of options to pass to use Phoenix.Channel
. For example, to turn off logging of each handle_in
:
config :drab, :phoenix_channel_options, [log_handle_in: false]
This release introduces core API changes, and the important new feature: creating reusable components!
use Drab.Controller
is now optionalWhen using default commander name, corresponding to the controller (like PageCommander -> PageController), there is no need to mark controller as Drab.Controller
anymore.
All shared commanders must be explicitly declared in the controller:
use Drab.Controller, commanders: [My.Shared.Commander]
In this version, system generates warning message if commanders are not declared. This warning will become error in v0.8.0
defhandler
macro for creating event handlers in commandersSince this version, all event handlers, whenever they are in shared or "normal" commander, must be declared with public
or defhandler
macro. Use defhandler
instead of the standard def
.
This:
public :button_clicked
def button_clicked(socket, sender), do: ...
is an equivalent of:
defhandler button_clicked(socket, sender), do: ...
In this version, system generates warning message if the function is not declared as handler. This warning will become error in v0.8.0
Accomplished this with the new Drab.Core.this_commander/1
function, returning the unique selector of the sourrounding commander tag, so you may easly reduce the region where your update works.
Having the page as below, we want the button to update .spaceholder1
only within the range of drab-commander
.
<div drab-commander="DrabTestApp.Shared1Commander">
<div class="spaceholder1">Nothing</div>
<button drab-click="button_clicked">Shared 1</button>
</div>
<div drab-commander="DrabTestApp.Shared1Commander">
<div class="spaceholder1">Nothing</div>
<button drab-click="button_clicked">Shared 2</button>
</div>
Just like we can use Drab.Core.this/1
to select the exact sender of the event, we may have Drab.Core.this_commander/1
, to build a selector which chooses the desired object:
defhandler button_clicked(socket, sender) do
set_prop socket, this_commander(sender) <> " .spaceholder1", innerText: "changed"
end
Notice the space before “.spaceholder1”. this_commander/1
returns the string like [drab-id="f59d54e6-a924-4e72-90d1-5177efecac9b"]
, so you may build any selector based on it.
This version is a step forward for creating component-like pieces of code with Drab, with enhanced Shared Commanders and possibility to pass additional argument to the handler function.
Finally, most functions got their own @spec
and Drab is now dialyzable.
Drab.Live
cache DETS has changed, please ensure your "*.drab
templates are recompiled after the upgrade.
drab-commander
on all children nodesIf you add drab-commander
attribute to any tag, all children of this tag will use Shared Commander defined in this tag. Notice it will not redefine nodes, which already has Shared Commander defined.
Thus this:
<div drab-commander="DrabExample.SharedCommander">
<button drab-click="button1_clicked">1</button>
<button drab-click="button2_clicked">1</button>
<button drab-click="DrabExample.AnotherCommander.button3_clicked">1</button>
</div>
is equivalent of:
<div>
<button drab-click="DrabExample.SharedCommander.button1_clicked">1</button>
<button drab-click="DrabExample.SharedCommander.button2_clicked">1</button>
<button drab-click="DrabExample.AnotherCommander.button3_clicked">1</button>
</div>
Since this version you may create handler with arity of 3, and pass the additional parameter using parenthesis after the handler name in drab
attribute:
<button drab-click='button_clicked(42)'>
This will run button_clicked/3
instead of button_clicked/2
in your Commander:
def button_clicked(socket, sender, the_answer_for_the_ultimate_question)
The attribute is evaluated on the client side, so it could be any valid JS expression:
<button drab-click='button_clicked({the_answer: 42})'>
<button drab-click='button_clicked(window.location)'>
drab-argument
Analogically to drab-commander
attribute, there is a drab-argument
to set this argument for more nodes. Notice that the existing arguments are not overwritten, so this:
<div drab-argument='42'>
<button drab-click='button_clicked'>
<button drab-click='button_clicked(43)'>
</div>
is the equivalent to:
<button drab-click='button_clicked(42)'>
<button drab-click='button_clicked(43)'>
For developer happines, all client-side errors are now displayed both on JS console and on the Phoenix side.
Example:
<button drab=":wrong">
generates:
[error] Browser reports: Drab attribute value ':wrong' is incorrect.
Drab.Element.set_prop
, fixed #80Updated the Drab core to introduce few important features. Fixed to Elixir version >= 1.5.2
. Tested with Elixir 1.6.0.
connect/2
callback for socket authentication, etcPreviously, Drab intercepted the connect/2
callback in your UserSocket
. Now, there is a possibility to use your own callback:
defmodule MyApp.UserSocket do
use Phoenix.Socket
channel "__drab:*", Drab.Channel
def connect(params, socket) do
Drab.Socket.verify(socket, params)
end
end
This version allow you to use of <%/ %>
marker to avoid using Drab.Live
for a given expression. The expression would be treaten as a normal Phoenix one, so will be displayed in rendered html, but Drab will have no access to it.
<div>
<%/ @this_assigns_will_be_displayed_but_not_drabbed %>
</div>
The existing syntax drab-event
and drab-handler
attributes does not allow having multiple events on the one DOM object (#73). This form is now depreciated and replaces with the brand new, better syntax of:
<tag drab="event:handler">
Now may set more event on the single object:
<input drab="focus:input_focus blur:input_blur"
or:
<input drab-focus="input_focus" drab-blur="input_blur">
By default, you can use only few arbitrary-chosen shorthands for the event name / handler name (drab-click="clicked"
) attribute. Now you may configure the list with :events_shorthands
config.
See #73.
@impl true
in behaviour callbacks@spec
(so far only few)Drab.Client.js/2
becomes Drab.Client.run/2
drab-event
and drab-handler
attributes combination replaced by drab
Changes:
Drab.Live.poke
returns {:error, description} on errorDrab.Live.assigns
(#72)Bug fixes:
value
attribute, poke
updates property as well (for inputs and textareas)