Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More Routing Options Needed / Components #2

Closed
nonfungibletunji opened this issue Nov 26, 2018 · 6 comments
Closed

More Routing Options Needed / Components #2

nonfungibletunji opened this issue Nov 26, 2018 · 6 comments

Comments

@nonfungibletunji
Copy link

The ability to add components, like header and footer as separate swift files, the vapor team suggested "that a controller-like class that has methods that return Html.Node (pointfree's type), which your route handler can call, effectively, you're replacing templates with Swift functions
which are needed to be known at compile time"

@mbrandonw
Copy link
Member

Hi @stunjiturner, I'm not sure I understand the question here. Can you clarify a bit more?

@marc-medley
Copy link

marc-medley commented Mar 22, 2019

@stunjiturner I see two parts in the original issue statement.

First, the swift-html-vapor main example only provides a single, monolithic page. How could swift-html be used to provide header component and a footer component which would be used across multiple pages (page_a, page_b, page_etc, ...)?

<html>
<head>
  <!-- -->
</head>
<body>
  <!-- some menu navigation here -->
  <!-- ## COMMON HEADER ABOVE HERE ## -->

  <!-- PAGE CONTENT: page_a, page_b, page_etc, ... -->

  <!-- ## COMMON FOOTER BELOW HERE ## -->
  <!-- may include some javascript -->
</body>
</html>

Extending/adapting the swift-html-vapor project to show how to use swift-html for common components that can be subsequently used to compose many pages would be helpful.

Second, swift-html-vapor appears to only support a statically compiled page which brakes when trying to use dynamic route parameters. See Issue #3

@mbrandonw
Copy link
Member

Hi @stunjiturner and @marc-medley, sorry for the delay in response. Here's a bit of info on how to accomplish what you want.

The nice thing having your HTML as simple swift data structures is that you can combine them in the same ways you might combine arrays and dictionaries. In particular, we could create a function that takes the main body of the page as an argument, and returns a new node that represents the page with the header and footer included:

func layout(mainContent: Node) -> Node {
  return .html(
    .head(
      // whatever you want in here
    ),
    .body(
      .header(
        .ul(
          .li(.a(attributes: [.href("/")], "Home")),
          .li(.a(attributes: [.href("/contact")], "Contact us")),
          .li(.a(attributes: [.href("/about")], "About"))
        )
      ),
      .main(
        mainContent
      )
      .footer(
        .ul(
          .li(.a(attributes: [.href("/")], "Home")),
          .li(.a(attributes: [.href("/contact")], "Contact us")),
          .li(.a(attributes: [.href("/about")], "About"))
        )
      )
    )
  )
}

Now all you have to do is pass your main page's content to the layout function and you will get a full formed page.

@stephencelis
Copy link
Member

@mbrandonw Maybe an action item before closing this out would be to refactor the example app to have a layout.

@marc-medley
Copy link

@stephencelis @mbrandonw

Regarding components, I am trying to extend a working SwifthtmlTemplateBlog.swift to inlcude the equivalent of Resources/HtmlParts/base_header.html and Resources/HtmlParts/base_footer.html with-in the swift-html code.

The following should be trivial, but the attempts so far only produce errors:

  • How to add <!DOCTYPE html>
  • How to add a script attributes including async

Also, when would one use the dot .p components versus a no-dot p components?

@mbrandonw
Copy link
Member

mbrandonw commented Mar 29, 2019

@marc-medley Hey Marc, seems like we really need to improve the documentation, both for this repo and swift-html proper! We'll work on that, but in the meantime here are some answers to your questions/concerns:

Regarding components, I am trying to extend a working SwifthtmlTemplateBlog.swift to inlcude the equivalent of Resources/HtmlParts/base_header.html and Resources/HtmlParts/base_footer.html with-in the swift-html code.

If you go back to the layout(mainContent:) function I posted above, we can break out the header and footer nodes into their own values that can be included into the layout:

let header =  Node.header(
  .ul(
    .li(.a(attributes: [.href("/")], "Home")),
    .li(.a(attributes: [.href("/contact")], "Contact us")),
    .li(.a(attributes: [.href("/about")], "About"))
  )
)

let footer =   Node.footer(
  .ul(
    .li(.a(attributes: [.href("/")], "Home")),
    .li(.a(attributes: [.href("/contact")], "Contact us")),
    .li(.a(attributes: [.href("/about")], "About"))
  )
)

func layout(mainContent: Node) -> Node {
  return .html(
    .head(
      // whatever you want in here
    ),
    .body(
     header
      .main(mainContent),
      footer
    )
  )
}

So instead of breaking out "partial" or "fragment" views into their own template files, you just create a value that holds the fragment and include it into a bigger document.

How to add

The doctype is a special case on the node enum, and can be used like so:

let document: Node = [
  .doctype,
  .html(
    .head(),
    .body()
  )
]

By default it uses a plain <!DOCTYPE html>, but if you need something custom:

let document: Node = [
  .doctype(#"HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"#),
  .html(
    .head(),
    .body()
  )
]

How to add a script attributes including async

Both the href and async are attributes on the script tag, so they are added like so:

.script(attributes: [
  .async(true),
  .src("https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js")
])

Also, when would one use the dot .p components versus a no-dot p components?

Yeah, sorry about the confusion here, but we recently refactored swift-html to use static functions instead of free functions, so pretty much everything is prefixed with a . now.

@pointfreeco pointfreeco locked and limited conversation to collaborators Aug 16, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants