temple icon indicating copy to clipboard operation
temple copied to clipboard

Dynamic attributes

Open formoxyz opened this issue 1 year ago • 3 comments

Is your feature request related to a problem? Please describe. I want to pass dynamic attributes to a node say div So i build the attributes as a keyword list like so

attrs = [class: "abc", id: "a1", "data-a1": "ABC", "data-a2": "DEF]

And then I create the div like so

temple do
	div attrs do
		"Hello World"
	end
end

It gives a runtime error that list cannot be converted into string

Describe the solution you'd like I don't know the solution but if attributes are keyword lists then the above should work in my opinion. Please advise if I am doing something wrong.

Describe alternatives you've considered I can build an exhaustive list of attributes and set those not applicable to false. Those won't be rendered in the final markup. But sometimes building an exhaustive list of attributes might not be possible.

Additional context Say you want to create some components and pass attributes dynamically to them. The attributes might not be known beforehand.

formoxyz avatar Oct 11 '22 11:10 formoxyz

I have taken this up in the discussion, where it should have been. Sorry I am closing it here.

formoxyz avatar Oct 12 '22 11:10 formoxyz

Re-opening as this doesn't currently work and needs a tracking issue.

We need something similar to how in heex you can do <div class="foo" {@rest}></div>

mhanberg avatar Oct 14 '22 01:10 mhanberg

I think the cleanest thing I can think of is

div let!: bar, class: "foobar", rest!: some_list do
  "hello world"
end

Here, we can observe several things. reserved keywords are suffixed by !. The let! is used for declaring a slot parameter (unrelated to this issue, but would be a change) and rest! is used for passing extra dynamic attributes to the tag.

The example in Phoenix.Component.assigns_to_attributes/2 could be written in temple as.

c &my_link/1, href: "/", id: @id, new_window: true, class: "my-class" do
  "Home"
end

def my_link(assigns) do
  target = if assigns[:new_window], do: "_blank", else: false
  extra = assigns_to_attributes(assigns, [:new_window])

  assigns =
    assigns
    |> assign(:target, target)
    |> assign(:extra, extra)

  temple do
    a href: @href, target: @target, rest!: @extra do
      slot @inner_block
    end
  end
end

Not sure what the best reserved keyword would be, could go with rest! or extra!.

mhanberg avatar Oct 14 '22 01:10 mhanberg