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

text/template: can invoke method of pipeline result value #28577

Open
mei-rune opened this issue Nov 3, 2018 · 5 comments
Open

text/template: can invoke method of pipeline result value #28577

mei-rune opened this issue Nov 3, 2018 · 5 comments
Labels
FeatureRequest NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@mei-rune
Copy link

mei-rune commented Nov 3, 2018

can invoke method of pipeline result value

package main

import (
 "fmt"
  "bytes"
  "html/template"
)


type TextField struct {
    name string
    value string
}

func (field *TextField) SetValue( value string) *TextField {
   field.value = value
   return field
}

func (field *TextField) Render() template.HTML {
  return  template.HTML(`<input type="text" name="`+field.name+`">`+field.value+`</input>`)
}

func NewTextField(name string) *TextField  {
   return &TextField{name: name}
}

var funcs = template.FuncMap{
 "text_field": NewTextField,
 }


func main() {
     txt := `{{text_field "username" |SetValue .value |Render }}`

      var buf bytes.Buffer
      var tpl, _ = template.New("main").Funcs(funcs).Parse(txt)
     tpl.Execute(&buf, map[string]interface{}{"value": "world"});
	fmt.Println(buf.String())
	//Output <input type="text" name="username">world</input>
}

text_field return *TextField ptr,
"|SetValue .value" will invoke "func (field *TextField) SetValue( value string)"
"|Render" will invoke "func (field *TextField) Render()"

like

// {{text_field "username" |SetValue .value |Render }}
NewTextField("username").SetValue(xxxx).Render()

if method isnot exists then execute old behaviour.

My English is poor.
我的意恩是
现在模板将符号 '|' 之前的执行结果作来下一个方法(function)的最后一个参数, 那能不能将 '|' 后的方法作为前一次结果的成员函数(method),

@dmitshur dmitshur added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. FeatureRequest labels Nov 4, 2018
@dmitshur dmitshur added this to the Unplanned milestone Nov 4, 2018
@mvdan
Copy link
Member

mvdan commented Nov 10, 2018

@runner-mei I assume that this is a feature request to be able to chain methods via pipelines, is that correct?

Have you considered doing something like {{with $x := text_field "username" | call $x.Render }}?

Also note that currently the parser is the one that rejects undefined functions. If this feature were to get implemented, we'd have to drop that check entirely, as it would be impossible to tell if a function is defined or not at parse time.

I personally think this is not a good idea. It seems like you can already accomplish the task with the current template language, and we don't want to complicate the language unless strictly necessary.

/cc @robpike

@mei-rune
Copy link
Author

@mvdan yes, this is a feature request to be able to chain methods via pipelines.

no, We didn't give up that check entirely,result of function text_field is *TextField (not interface{}), We can try to obtain the return value type and check it.

@robpike
Copy link
Contributor

robpike commented Nov 12, 2018

I would prefer not to do this. The grammar is subtle enough as is, the execution logic even more so, and it is easy, as shown above, to achieve the desired result with the existing template language.

@mei-rune
Copy link
Author

mei-rune commented Nov 12, 2018

@robpike Now the grammar is insufficient, it is cumbersome。

It's a bug? the following statements are incorrect, they run ok and don't have any output

{{with $x := text_field "username" | call $x.SetValue .value | call $x.Render }}{{end}}
{{with $x := text_field "username" | call $x.SetValue .value | call $x.Render }}{{$x}}{{end}}
{{with $x := text_field "username"}}{{call $x.SetValue .value}}{{call $x.Render }}{{end}}
{{with $x := text_field "username" }} {{ $x.SetValue .value }} {{ $x.Render}} {{end}}
{{with $x := text_field "username" |  $x.SetValue .value |  $x.Render }}{{end}}
{{with $x := text_field "username" |  $x.SetValue .value |  $x.Render }}{{$x}}{{end}}
{{with text_field "username"}}{{ $.SetValue .value |  $.Render }}{{end}}
{{with text_field "username"}}{{call  $.SetValue .value  }}{{ call $.Render }}{{end}}

only the following statements are correct

{{with $x := text_field "username" }} {{ $x.Render}} {{end}}  // but cannot invoke SetValue  in the with block

@mei-rune
Copy link
Author

or add '@' prefix

{{text_field "username" |@SetValue .value |@Render }}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FeatureRequest NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants