Skip to content

Latest commit

 

History

History
348 lines (293 loc) · 6.71 KB

view.md

File metadata and controls

348 lines (293 loc) · 6.71 KB

View

back

Table of Contents

Introduction

There are 4 ways to render HTML in Basolato. Although each library has it's own benefits and drawbacks, every library can be used.
Basolato use nim-templates as a default template engin. It can be used by importing basolato/view.

LibraryBenefitsDrawbacks
htmlgen
  • Nim standard library
  • Easy to use for Nim programmer
  • Available to define plural Procedures in one file
  • Cannot use `if` statement and `for` statement
  • Maybe difficult to collaborate with designer or markup enginner
SCF
  • Nim standard library
  • Available to use `if` statement and `for` statement
  • Easy to collaborate with designer or markup enginner
    • Cannot define plural Procedures in one file
    Karax
  • Available to define plural Procedures in one file
  • Available to use `if` statement and `for` statement
    • Maybe difficult to collaborate with designer or markup enginner
    nim-templates
    • Available to define plural Procedures in one file
    • Available to use `if` statement and `for` statement
    • Easy to collaborate with designer or markup enginner
    • Maintained by a person

    Views file should be in resources dir.

    Csrf Token

    To send POST request from form, you have to set csrf token. You can use helper function from basolato/view

    nim-templates

    import basolato/view
    
    proc index*():string = tmpli html"""
    <form>
      $(csrfToken())
      <input type="text", name="name">
    </form>
    """

    htmlgen

    import htmlgen
    import basolato/view
    
    proc index*():string =
      form(
        csrfToken(),
        input(type="text", name="name")
      )

    SCF

    #? stdtmpl | standard
    #import basolato/view
    #proc index*():string =
    <form>
      ${csrfToken()}
      <input type="text", name="name">
    </form>

    Karax

    import basolato/view
    import karax / [karaxdsl, vdom]
    
    proc index*():string =
      var vnode = buildView(form):
        csrfTokenKarax()
        input(type="text", name="name")
      return $vnode

    Block components example

    Controller and result is same for each example.

    controller

    proc index*(): Response =
      let message = "Basolato"
      return render(indexView(message))

    result

    <html>
      <head>
        <title>Basolato</title>
      </head>
      <body>
        <p>Basolato</p>
      </body>
    </html>

    nim-templates

    import basolato/view
    
    proc baseImpl(content:string): string = tmpli html"""
    <html>
      <heade>
        <title>Basolato</title>
      </head>
      <body>
        $(content)
      </body>
    </html>
    """
    
    proc indexImpl(message:string): string = tmpli html"""
    <p>$message</p>
    """
    
    proc indexView*(message:string): string =
      baseImpl(indexImpl(message))

    htmlgen

    import htmlgen
    
    proc baseImpl(content:string): string =
      html(
        head(
          title("Basolato")
        ),
        body(content)
      )
    
    proc indexImpl(message:string): string =
      p(message)
    
    proc indexView*(message:string): string =
      baseImpl(indexImpl(message))

    SCF

    SCF should divide procs for each file

    baseImpl.nim

    #? stdtmpl | standard
    #proc baseImpl*(content:string): string =
    <html>
      <heade>
        <title>Basolato</title>
      </head>
      <body>
        $content
      </body>
    </html>

    indexImpl.nim

    #? stdtmpl | standard
    #proc indexImpl*(message:string): string =
    <p>$message</p>

    index_view.nim

    #? stdtmpl | standard
    #import baseImpl
    #import indexImpl
    #proc indexView*(message:string): string =
    ${baseImpl(indexImpl(message))}

    Karax

    This usage is Server Side HTML Rendering

    import karax / [karasdsl, vdom]
    
    proc baseImpl(content:string): string =
      var vnode = buildView(html):
        head:
          title: text("Basolato")
        body: text(content)
      return $vnode
    
    proc indexImpl(message:string): string =
      var vnode = buildView(p):
        text(message)
      return $vnode
    
    proc indexView*(message:string): string =
      baseImpl(indexImpl(message))

    old helper

    If the user's input value is invalid and you want to back the input page and display the previously entered value, you can use old helper function.

    controller

    # get access
    proc signinPage*(this:LoginController):Response =
      return render(this.view.signinView())
    
    # post access
    proc signin(this:LoginController):Response =
      let params = this.request.params()
      let email = params["email"]
      try
        ...
      except:
        return render(Http422, this.view.signinView(%params))

    view

    proc impl(params=newJObject()):string = tmpli html"""
    <input type="text" name="email" value="$(old(params, "email"))">
    <input type="text" name="password">
    """
    
    proc signinView*(this:View, params=newJObject()):string =
      let title = "SignIn"
      return this.applicationView(title, impl(params))

    It display value if params has key email, otherwise display empty string.

    Auth

    You can access auth in view like bellow.

    controller

    proc home*(this:StaticPageController):Response =
      return render(this.view.homeView())

    view

    import basolato/view
    
    proc headerView*(auth:Auth):string = tmpli html"""
    <header>
      <ul>
        $if auth.isLogin(){
          <li>$(auth.get("id"))</li>
        }
        $else{
          <li><a href="/login">Log In</a></li>
        }
      </ul>
    </header>
    
    
    proc applicationView*(this:View, title:string, body:string, flash=newJObject()):string = tmpli html"""
    <!DOCTYPE html>
    <html>
      <head>
      </head>
      <body>
        $(headerView(this.auth))
        ...
      </body>
    </html>
    
    proc homeView*(this:View):string =
      this.applicationView("Title", impl())
    """