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
runner-mei opened this issue Nov 3, 2018 · 5 comments
Open

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

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

Comments

@runner-mei
Copy link

@runner-mei runner-mei 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),

@mvdan

This comment has been minimized.

Copy link
Member

@mvdan 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

@runner-mei

This comment has been minimized.

Copy link
Author

@runner-mei runner-mei commented Nov 11, 2018

@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

This comment has been minimized.

Copy link
Contributor

@robpike 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.

@runner-mei

This comment has been minimized.

Copy link
Author

@runner-mei runner-mei 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
@runner-mei

This comment has been minimized.

Copy link
Author

@runner-mei runner-mei commented Nov 12, 2018

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
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.