Golang模板FuncMap可以调用自己

时间:2017-04-07 17:47:48

标签: go

我正在尝试在基本模板中实现添加到FuncMaps的函数,并且此函数应该用于呈现可重用的视图组件

例如:

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())
}

此代码适用于不会渲染其他组件的组件。例如,我可以编写{{component "buttons/default-button" "some url goes here"}},它会在components/button/default-button.tmpl处呈现组件就好了。

但是,如果我在该默认按钮组件中包含另一个组件,例如{{component "icons/check-icon"}},我将收到一个很大的错误(太大而无法在此处粘贴)。但这是一条错误消息:

  

template:default-button.tmpl:4:function" component"未定义

如您所见,从尝试调用另一个组件的组件文件中抛出错误。我相信这是因为viewFunc要么没有被正确添加,要么以某种方式递归调用。

1 个答案:

答案 0 :(得分: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)

......对此:

// 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'

我引用了template包而不是我创建的t模板。我还传递了template.New的错误名称,因为它需要完整填充,例如index.tmpl,而不只是index

现在一切都按预期工作了!可以从另一个组件调用组件。