Расширение Groovy MarkupTemplateEngine с помощью классов Mixin - PullRequest
0 голосов
/ 09 июля 2019

Я использую Groovy MarkupTemplateEngine для генерации xhtml

Я хотел бы иметь библиотеку классов расширений, которые могут быть смешаны с классом BaseTemplate по требованию. Например, служебный класс


class FormField {

    static void textField(String title, String content) {

        div(class: 'form-field') {
            div(title, class: 'form-field-label')
            div(content, class: 'form-field-content')
        }

    }


    static void checkboxField(String title, boolean state) {

        String suffix = state ? 'checked' : 'unchecked';
        String src = 'img/common/checkbox_' + suffix + '.svg';


        img(src: src, class: 'checkbox-image')
        span(title, class: 'form-field-label')
    }
}

Они предоставляют конструкции более высокого уровня, которые вы можете смешать с вашим шаблоном, если они вам нужны

Я знаю, что вы можете добавить эти методы в пользовательский базовый шаблонный класс, но тогда вы потенциально добавите много методов в один класс, и у вас не будет поддержки автозаполнения IDE.

Вот что я пытался:

abstract class ExtendedBaseTemplate extends BaseTemplate {


    ExtendedBaseTemplate(MarkupTemplateEngine templateEngine,
                         Map model, Map<String, String> modelTypes,
                         TemplateConfiguration configuration) {

        super(templateEngine, model, modelTypes, configuration)
    }


    // single extension method
    void f0() {
        p('hi from f0()')
    }
}

И какой-то тестовый шаблон

assert GroovySystem.version == '2.5.7'
assert this instanceof BaseTemplate
assert this.class.getSimpleName().startsWith('GeneratedMarkupTemplate')


def f1() {
    p('hi from f1()')
}
assert this.metaClass.methods*.name.contains('f1')


// add a new method via metaClass
this.metaClass.f2 = {
    p('hi from f2()')
}
// seems to have worked
assert this.metaClass.methods*.name.contains('f2')


// TODO mixin some required utility classes here 


html {
    body {
        h1('Test')


        // ok renders as <p>`hi from f0()`</p>
        f0()

        // ok rendered as <p>hi from f1()</p>
        f1()

        // What? rendered as <p>hi from f2()</p>
        p(f2())

        // What? rendered as <f2/> -> method missing
        f2()
    }
}

Мне даже не удалось добавить дополнительный метод (f2 ()) через шаблон метакласса. Несмотря на то, что он доступен в шаблоне, он не работает должным образом

...