Packages
surface
0.5.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.1
0.1.0
0.1.0-alpha.2
0.1.0-alpha.1
0.1.0-alpha.0
A component based library for Phoenix LiveView
Current section
Files
Jump to
Current section
Files
lib/surface/components/link.ex
defmodule Surface.Components.Link do
@moduledoc """
Generates a link to the given URL.
Provides similar capabilities to Phoenix's built-in `link/2` function.
Options `label` and `class` can be set directly and will override anything in `opts`.
All other options are forwarded to the underlying <a> tag.
## Examples
```
<Link
label="user"
to="/users/1"
class="is-danger"
method={{ :delete }}
opts={{ data: [confirm: "Really?"] }}
/>
<Link
to="/users/1"
class="is-link"
>
<span>user</span>
</Link>
```
"""
use Surface.Component
use Surface.Components.Events
import Surface.Components.Utils
@doc "The page to link to"
prop to, :any, required: true
@doc "The method to use with the link"
prop method, :atom, default: :get
@doc "Id to apply to the link"
prop id, :string
@doc "Class or classes to apply to the link"
prop class, :css_class
@doc """
The label for the generated `<a>` element, if no content (default slot) is provided.
"""
prop label, :string
@doc """
Additional attributes to add onto the generated element
"""
prop opts, :keyword, default: []
@doc """
The content of the generated `<a>` element. If no content is provided,
the value of property `label` is used instead.
"""
slot default
def render(assigns) do
valid_label!(assigns)
to = valid_destination!(assigns.to, "<Link />")
~F"""
<a id={@id} class={@class} href={to} :attrs={to_attrs(assigns, to)}><#slot>{@label}</#slot></a>
"""
end
defp valid_label!(assigns) do
unless assigns[:default] || assigns[:label] || Keyword.get(assigns.opts, :label) do
raise ArgumentError, "<Link /> requires a label prop or contents in the default slot"
end
end
defp apply_method(to, method, opts) do
if method == :get do
skip_csrf(opts)
else
{csrf_data, opts} = csrf_data(to, opts)
opts = Keyword.put_new(opts, :rel, "nofollow")
[data: [method: method, to: to] ++ csrf_data] ++ opts
end
end
defp to_attrs(assigns, to) do
(apply_method(to, assigns.method, assigns.opts) ++ events_to_opts(assigns))
|> opts_to_attrs()
end
end