英文:
Golang template FuncMap that can call itself
问题
我正在尝试实现一个函数,将其添加到基本模板的FuncMaps中,该函数应用于渲染可重用的视图组件。
例如:
func (v *Item) RenderComponent(componentPath string, vars ...interface{}) template.HTML {
p := path.Join(v.folder, "components", componentPath)
// 获取组件路径的各个部分
componentPathPieces := strings.Split(p, "/")
// 获取部分中的最后一项(应该是文件名)
componentFileName := componentPathPieces[len(componentPathPieces)-1]
// 使用组件文件名创建新模板,并添加FuncMap函数
t := template.New(componentFileName).Funcs(v.funcMap)
// 检查模板语法是否有错误
t, err := template.ParseFiles(p + "." + v.extension)
if err != nil {
panic(err)
}
// 将变量添加到组件中,并将结果写入缓冲区
b := new(bytes.Buffer)
if err = t.Execute(b, vars); err != nil {
panic(err)
}
// 将模板缓冲区的内容作为HTML字符串返回
return template.HTML(b.String())
}
这段代码对于不渲染其他组件的组件来说是正常工作的。例如,我可以写{{component "buttons/default-button" "some url goes here"}}
,它会正常渲染位于components/button/default-button.tmpl
的组件。
然而,如果我在default-button组件中包含另一个组件,比如{{component "icons/check-icon"}}
,我会得到一个很长的错误(太长无法在此处粘贴)。但是这里是其中一个错误消息:
template: default-button.tmpl:4: function "component" not defined
如你所见,错误是从试图调用另一个组件的组件文件中抛出的。我认为这是因为viewFunc要么没有被正确添加,要么以某种方式被递归调用了。
英文:
I am trying to achieve a function to add to FuncMaps in a base template, and this function should be used to render re-useable view components
For instance:
func (v *Item) RenderComponent(componentPath string, vars ...interface{}) template.HTML {
p := path.Join(v.folder, "components", componentPath)
// Get the pieces of the component path.
componentPathPieces := strings.Split(p, "/")
// Get the last item in the pieces (this should be the file name).
componentFileName := componentPathPieces[len(componentPathPieces)-1]
// Make the new template using component file name and add FuncMap functions.
t := template.New(componentFileName).Funcs(v.funcMap)
// Determine if there is an error in the template syntax.
t, err := template.ParseFiles(p + "." + v.extension)
if err != nil {
panic(err)
}
// Add variables to the component and write to a buffer.
b := new(bytes.Buffer)
if err = t.Execute(b, vars); err != nil {
panic(err)
}
// Return the contents of the template buffer as a string of HTML.
return template.HTML(b.String())
}
This code works just fine for a component that doesn't render another component. For example, I can write {{component "buttons/default-button" "some url goes here"}}
and it will render the component at components/button/default-button.tmpl
just fine.
However, if I include another component within that default-button component, such as {{component "icons/check-icon"}}
, I will get a large error (too big to paste here). But here is one of the error messages:
> template: default-button.tmpl:4: function "component" not defined
As you can see, the error is thrown from the component file that is trying to call another component. I believe that happens because the viewFunc is either not being properly added, or is being recursively called in some way.
答案1
得分: 2
翻译结果如下:
哎呀,看起来我打错了字。
需要将这段代码修改为:
// 使用组件文件名创建新模板,并添加FuncMap函数。
t := template.New(componentFileName + "." + v.extension).Funcs(v.funcMap) // <---- 将'componentFileName'修改为'componentFileName + "." + v.extension'
// 检查模板语法是否有错误。
t, err := t.ParseFiles(p + "." + v.extension) // <---- 将'template'修改为't'
我之前引用了template
包而不是我创建的t
模板。我还传入了错误的名称给template.New
,因为它期望一个完整的文件名,比如index.tmpl
,而不仅仅是index
。
现在一切都按预期工作了!可以从另一个组件调用组件。
英文:
Oops, looked like I had a typo.
Had to change this:
// Make the new template using component file name and add FuncMap functions.
t := template.New(componentFileName).Funcs(v.funcMap)
// Determine if there is an error in the template syntax.
t, err := template.ParseFiles(p + "." + v.extension)
...to this:
// Make the new template using component file name and add FuncMap functions.
t := template.New(componentFileName + "." + v.extension).Funcs(v.funcMap) // <---- 'componentFileName' to 'componentFileName + "." + v.extension'
// Determine if there is an error in the template syntax.
t, err := t.ParseFiles(p + "." + v.extension) // <---- 'template' to 't'
I was referencing the template
package instead of the t
template that I created. I also passed in the wrong name for template.New
, since that expects a full fill such as index.tmpl
, instead of just index
.
Now everything works as expected! Can call component from another component.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论