【问题标题】:KTOR DSL - how to nest templates?KTOR DSL - 如何嵌套模板?
【发布时间】:2021-07-02 17:11:49
【问题描述】:

我正在尝试使用 KTOR DSL 将 HTML 模板相互嵌套,看起来应该非常简单,但文档让我无处可去,而且我尝试过的任何东西都没有编译或工作。

我定义了一个根级页面模板,它需要一个名为“pageContent”的占位符,我正在尝试使用路由来确定应该将哪个页面级模板作为 HTML 内容注入。所以 PageTemplate 看起来像这样:

class PageTemplate(private val username: String, private val displayName: String) : Template<HTML> {
    val pageContent = Placeholder<FlowContent>()
    
    override fun HTML.apply() {
        head {
            title { +"Page Title" }
            stylelink("lots of style and script, etc")
        }
        body("body classes") {
            header {...} //display logged-in user's name here, nav, etc
            main("some classes") {
                insert(pageContent)
            }
        }
    }
}

我的路由看起来像这样:

get("/example-path") {
    call.respondHtmlTemplate(PageTemplate(call.session?.username, call.session?.displayName)) {
        pageContent {
            ExamplePathTemplate(call.session?.username)
        }
    }
}

这个想法是让每个路由都用自己的路径特定模板覆盖 pageContent。

上面的代码编译。但是,当我运行它时,实际上从未调用过 ExamplePathTemplate。我也尝试过在insert(ExamplePathTemplate(...), pageContent) 上使用变体,但由于某种类型不匹配而无法编译。感觉这应该是我应该能够使用 KTOR 完成的一件显而易见的事情——有人知道我可能会错过什么吗?

【问题讨论】:

  • 显示您的PageTemplate 课程
  • 由于 API 笨拙,这一点并不明显。
  • @МихаилНафталь 我已经用 PageTemplate 类的示例更新了这个问题

标签: kotlin ktor


【解决方案1】:

如果pageContent 属性应该是另一个模板的占位符,那么它的类型应该是TemplatePlaceholder,而不仅仅是简单的Placeholder

如果事先不知道Template 的类型,那么PageTemplate 类应该成为泛型并接受Template 的实例作为参数:

class PageTemplate<T : Template<FlowContent>>(private val username: String, private val displayName: String, private val template: T) : Template<HTML> {
    val pageContent = TemplatePlaceholder<T>()

    override fun HTML.apply() {
        head {
            title { +"Page Title" }
        }
        body("body classes") {
            header {/*...*/ } //display logged-in user's name here, nav, etc
            main("some classes") {
                insert(template, pageContent)
            }
        }
    }
}

用法:

get("/example-path") {
    call.respondHtmlTemplate(PageTemplate(call.session?.username, call.session?.displayName, ExamplePathTemplate(call.session?.username))) {
        pageContent { //this: ExamplePathTemplate
            /*set inner template parameters here*/
        }
    }
}

【讨论】:

    【解决方案2】:

    通过将路由更改为如下所示,我能够将特定于页面的模板应用于页面内容:

    get("/example-path") {
        call.respondHtmlTemplate(PageTemplate(call.session?.username, call.session?.displayName)) {
            pageContent {
                insert(ExamplePathTemplate(call.session?.username)) { }
            }
        }
    }
    

    这样就满足了编译器的类型要求,成功地用插入的模板生成的html覆盖了pageContent占位符。

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 2021-04-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-14
      • 2012-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多