Packages
surface
0.11.2
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
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
to = valid_destination!(assigns.to, "<Link />")
events = events_to_opts(assigns)
opts = link_method(assigns.method, to, assigns.opts)
assigns = assign(assigns, to: to, opts: events ++ opts)
~F"""
<a id={@id} class={@class} href={@to} :attrs={@opts}><#slot>{@label}</#slot></a>
"""
end
defp link_method(method, to, opts) do
if method == :get do
skip_csrf(opts)
else
{csrf_data, opts} = csrf_data(to, opts)
data =
opts
|> Keyword.get(:data, [])
|> Keyword.merge(csrf_data)
|> Keyword.merge(method: method, to: to)
Keyword.merge(opts, data: data, rel: "nofollow")
end
end
end