Skip to content
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

Template macros #7

Closed
ahall opened this issue Apr 20, 2014 · 9 comments
Closed

Template macros #7

ahall opened this issue Apr 20, 2014 · 9 comments

Comments

@ahall
Copy link

ahall commented Apr 20, 2014

In templates I find myself writing the same template stuff e.g. render input forms with twitter bootstrap classes around it over and over again and was wondering if something like template macros in jinja2 could be implemented. First they could be imported from another file and then reused.

For example I want to make a template macro called renderInput that generates a form input I'd like to create a reusable gold helper in helpers.gold file. See http://jinja.pocoo.org/docs/templates/#macros for something similar.

I'm not sure if this is possible, but thought I'd raise it here.

@yosssi
Copy link
Owner

yosssi commented Apr 20, 2014

@ahall Thanks for your comment! I'll check the function later. Just a moment, please!

@yosssi
Copy link
Owner

yosssi commented Apr 21, 2014

@ahall Hi, I just added a macro function on Gold. There are two ways to use this function.

1. Use a helper function

You can define a helper function and call it on Gold templates. Here is an example:

main.go

package main

import (
    "fmt"
    "html/template"
    "os"

    "github.com/yosssi/gold"
)

var funcMap = template.FuncMap{
    "inputHandler": func(id string, name string) template.HTML {
        return template.HTML(fmt.Sprintf(`<input type="text" id="%s" name="%s">`, id, name))
    },
}

var g = gold.NewGenerator(false).SetHelpers(funcMap)

func main() {
    tpl, err := g.ParseFile("./main.gold")
    if err != nil {
        panic(err)
    }
    tpl.Execute(os.Stdout, nil)
}

main.gold

doctype html
html
  body
    form
      = inputHandler "Foo" "Bar"

The output is:

<!DOCTYPE html>
<html>
  <body>
    <form>
      <input type="text" id="Foo" name="Bar">
    </form>
  </body>
</html>

2. Use an include function

You can include Gold templates from other Gold templates. Here is an example:

package main

import (
    "os"

    "github.com/yosssi/gold"
)

var g = gold.NewGenerator(false)

func main() {
    tpl, err := g.ParseFile("./main.gold")
    if err != nil {
        panic(err)
    }
    data := map[string]interface{}{"Name": "Bar"}
    tpl.Execute(os.Stdout, data)
}

main.gold

doctype html
html
  body
    form
      include ./input id="Foo" name="{{.Name}}"

input.gold

input id=%{id} name=%{name}

The output is:

<!DOCTYPE html>
<html>
  <body>
    <form>
      <input id="Foo" name="Bar"></input>
    </form>
  </body>
</html>

Please check this function.

@ahall
Copy link
Author

ahall commented Apr 21, 2014

Hi @yosssi. This is impressive and works very well.

One thing I think we would improve if you could specify a base directory where your engine looks for templates so instead of doing include ../helpers/blah you could do: include helpers/blah and you tell the engine that your template base dir is /path/to/basedir and it only ever lets you look inside there.

Not sure how that could be implemented without a breaking change unless you add it to the generator. What you really want is an area where templates are as its own sandbox and reference stuff that way e.g. extends layout, include helpers/my_helper. You could add it as a property to the generator and if the property is set then use the sandbox, otherwise default behaviour. Or even add a template locator function a user of the library can implement and pass in. Let me know what you think and if you think it makes sense we could close this issue and open a new one.

@ahall
Copy link
Author

ahall commented Apr 21, 2014

Any way of doing something like this:
input name="{{$field}}" type="text" class="form-control" placeholder="%{placeholder}" value="%{value}" {{if $required}}required="required"{{end}}

I'm passing:
include ./test_helper name="name" value="" placeholder="My Name" icon="icon-envelope" required="true"

Just wondering if the processing I'm trying to do with required is possible, at least doesn't work the way I tried :)

@yosssi
Copy link
Owner

yosssi commented Apr 21, 2014

@ahall Thanks for your comment! You can write the following code:

test_helper.gold

input name="%{name}" type="text" class="form-control" placeholder="%{placeholder}" value="%{value}" required="{{if %{required}}}required{{end}}"

@ahall
Copy link
Author

ahall commented Apr 21, 2014

that wont work because even if required="" it will treat it as required as the html attribute is there, so I must make sure its set or NOT at all :).

What you think about my template locating idea mentioned above, do you agree with it?

@yosssi
Copy link
Owner

yosssi commented Apr 21, 2014

@ahall

that wont work because even if required="" it will treat it as required as the html attribute is there, so I must make sure its set or NOT at all :).

Oh, I see. Please give me time to handle with this.

What you think about my template locating idea mentioned above, do you agree with it?

Yes, I agree with it. Thank you very much for your idea! I'll consider to implement this function later.

@yosssi
Copy link
Owner

yosssi commented Apr 21, 2014

@ahall Hi, I fixed Gold to accept a single(non key-value) attribute(like "required" or "checked"). Please get the latest Gold modules and try the following code:

input name="%{name}" type="text" class="form-control" placeholder="%{placeholder}" value="%{value}" [{{if %{required}}}required{{end}}]

[] lets Gold know that it is a single(non key-value) attribute.

@ahall
Copy link
Author

ahall commented Apr 21, 2014

Absolutely fantastic @yosssi. Closing this now and opening a new one with the template locating stuff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants