wkhere / webassembly

Web DSL for Elixir
BSD 2-Clause "Simplified" License
73 stars 9 forks source link

Examples of "partials" #10

Open wkhere opened 9 years ago

collin commented 9 years ago

I greatly prefer the builder style for creating html, but reuse-ability is definitely key. Is there a way to do 'partials' or call out to other functions to dry up repetive stuff like form input wrappers (etc)?

decapo01 commented 5 years ago

This is exactly what I've been looking for. How do you do partials?

wkhere commented 5 years ago

Hello.

Unfortunately partials occured to be broken due to the fact how builder macro works. It can hardly be fixed without a big internal redesign.

Sorry to say that... I am not using Elixir very actively nowadays.

This issue should be renamed as it is misleading- suggests that partials are working as we expect from other frameworks/libs.

decapo01 commented 5 years ago

I actually figured out a way to get this working with what you have. I meant to comment on this but I also stopped working in elixir. I'm not sure how maintainable this is but if you specify the text tag you can put more html inside.

def layout(content) do
    use WebAssembly
    builder do
      html do
        head do
          title "Home"
        end
        body do
          div class: "container" do
            h1 "Hello"
            ul do
              li "list item 1"
              li "list item 2"
            end
            div do
              text content
            end
          end
        end
      end
    end
  end

  def home_content([%Person{} | _] = persons) do
    use WebAssembly
    builder do
      div class: "some-class" do
        h2 "This is home content"
          for per <- persons, do:
            p "#{per.name} #{per.age}"
        div do
          p "another paragraph"
        end
      end
    end
  end

I was able to get that to work with a phoenix controller like this

  def about(conn, _params) do
    p = [
      newPerson("jim", 232),
      newPerson("will",23)
    ]
    conn
      |> put_resp_content_type("text/html", "utf-8")
      |> send_resp(200,home(home_content(p)))
  end
wkhere commented 5 years ago

Interesting. Yeah.

I was aiming at more ambitious solution but this may work.

Thank you, it is going to get me to bring back my Elixir hacking env, not tomorrow but hopefully soon.

wkhere commented 5 years ago

I think the text macro could be aliased to eval to make it more clear that in this context we want to evaluate what comes from another builder invocation, what do you think? Would it make the code more readable?

decapo01 commented 5 years ago

Yeah I think eval sounds right for that situation. I was taking a break from scala when I tried this. The play framework has a type safe templating engine and I was trying to mimic that in elixir which is what brought me here. You can user the linter to tell you if you have errors for whatever structure you put in without having to load the page. I probably won't be using elixir much anytime soon though so whatever you call it is cool with me.

wkhere commented 5 years ago

Optimistic type safety, generally possible in Erlang/Elixir with dialyzer, is used in WebAssembly, but this all works in a slightly different way than you may expect.

Main point of WebAssembly is that you can intermix html DSL and regular Elixir language; it's done in a way that DSL is actually macros which modify via Agent API the process-local stack of html element "scopes" (core.ex) and the whole processing is actually done at runtime.

So, dialyzer can prove that calls from DSL to this Agent machinery implementation are type safe (for the quite relaxed definition of possible inputs/outputs, see types.ex) but that's it, it has nothing to do with the correctness of the code describing the page, or partial. I would of course love to have it but I don't know how to do it while still retaining this property of mixed WebAssembly DSL & Elixir.

I would recap that the advantages of WebAssembly are: