maxence-charriere / go-app

A package to build progressive web apps with Go programming language and WebAssembly.
https://go-app.dev
MIT License
7.96k stars 367 forks source link

Arithmetic in Go templates #88

Closed XWCHAO closed 6 years ago

XWCHAO commented 6 years ago

Hi,

I'd like to do some simple arithmetic calculations in html template. For example, {{.X}}+1. I googled about this and most people believe a new template function should be written and called whenever need to calculate. Here's a example link:

https://stackoverflow.com/questions/25689829/arithmetic-in-go-templates

However, since your code have this "Parse" process in the back. I don't know where to define a function like this. Could you please help me out?

maxence-charriere commented 6 years ago

The package use just the template syntaxe for generating html. Because it handle all the logic to translate component to html, you can't do all the feature that the standard template package do.

A solution for that would be to implement the TemplateFuncMapper interface => https://github.com/murlokswarm/app/blob/master/component.go#L39

you could do something like:

func (c *YourComponent) FuncMaps() template.FuncMap {
    return template.FuncMap{
        "add": func(x, y int) int {
            return x + y
        },
    }
}

func (c *YourComponent) Render() string {
    return `
<div>
    x + 1 = {{add .X 1}}
</div>
    `
}

But honestly, I think your html should just contain your interface description. This kind of operation should be done in go code.

XWCHAO commented 6 years ago

I tested your suggestions. In the returned html string of Render(), I have the following code.

{{range $i, $row := .Board}}
        {{range $j, $elem := $row}}
            {{if eq $elem 1}}
                <circle cx="{{add 15 $i}}" cy="{{add 15 $j}}" r="12" fill="url(#grad)" />
            {{else if eq $elem 2}}
                <circle cx="{add 15 $i}}" cy="{{add 15 $j}}" r="12" fill="white" />
            {{end}}
        {{end}}
      {{end}}

And in the go part, I added the following function:

func (g *Gobang) FuncMaps() template.FuncMap {
    return template.FuncMap{
        "add": func(x, y int) int {
            return x + y
        },
    }
}

I can build it. But when I run it, I got the error: panic: template: Render:65: function "add" not defined How could that be?

maxence-charriere commented 6 years ago

Is it template/text or template/html that is imported ?

Sent from my iPhone

On Dec 2, 2017, at 1:47 PM, Xiwen Zhao notifications@github.com<mailto:notifications@github.com> wrote:

I tested your suggestions. In the returned html string of Render(), I have the following code.

{{range $i, $row := .Board}} {{range $j, $elem := $row}} {{if eq $elem 1}}

            {{else if eq $elem 2}}
                    <circle cx="{add 15 $i}}" cy="{{add 15 $j}}" r="12" fill="white" />
            {{end}}
    {{end}}
  {{end}}

And in the go part, I added the following function:

func (g *Gobang) FuncMaps() template.FuncMap { return template.FuncMap{ "add": func(x, y int) int { return x + y }, } }

I can build it. But when I run it, I got the error: panic: template: Render:65: function "add" not defined How could that be?

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/murlokswarm/app/issues/88#issuecomment-348722530, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ACkWe3tO9bi99x2jEDvpFxtZQ6qQS1Ggks5s8cVxgaJpZM4QzbMo.

XWCHAO commented 6 years ago

Yes. I used html/template before. Now I changed to text/html, and "add" can be done normally.

However, when I want to do nested calculations, e.g. 15 + 30 * {{$i}}, the code below doesn't work. In html: {{add 15 {{multi 30 $i}}}} In go:

func (g *Gobang) FuncMaps() template.FuncMap {
    return template.FuncMap{
        "add": func(x, y int) int {
            return x + y
        },
                "multi": func(x, y int) int {
            return x * y
        },
    }
}

The error is: panic: template: Render:68: unexpected "{" in operand

So what should I do if I want to do add and multiply at the same time?

maxence-charriere commented 6 years ago

did you tried, {{add 15 multi 30 $i}}? Also I dont know if go template accept $i.

XWCHAO commented 6 years ago

I got the error: ERROR 2017/12/02 23:48:45 app.go:57: unable to render *main.Gobang: template: Render:68:23: executing "Render" at <add>: wrong number of args for add: want 2 got 4 So I think it doesn't work.

I tested with {{add 15 $i}} and {{multi 15 $i}}, they work. So I think go template can accept $i.

maxence-charriere commented 6 years ago

{{add 15 (multi 30 $i)}} => https://golang.org/pkg/text/template/#hdr-Examples

XWCHAO commented 6 years ago

Thanks!!!!! I fixed it.

Have a good day! :)