Kotlinx.html questions: subtree with DSL?


#1

kotlinx.html implements a very elegant DSL that allows describing the code to build a DOM.tree or subtree.

e.g. from readme page…

val myDiv = document.create.div("panel") {
    p { 
        +"Here is "
        a("http://kotlinlang.org") { +"official Kotlin site" } 
    }
    // sequence of tags can be added here
}

The questions is, how can the ‘sequence of tags’ be provided not by a set of declarations, but by a function that provides the set of declarations so in place of …

val myDiv = document.create.div("panel") {
    p { 
        +"Here is "
        a("http://kotlinlang.org") { +"official Kotlin site" } 
    }
   //  sequence 
   ul {
         li{  +"list item 1"}
         li{  +"list item n"}
   }
}

but instead something like…

fun doUl(){
    return document.create.ul{
        li{ +"item 1"}
        li{ +"item n"}
    }
}

//........
 val myDiv = document.create.div("panel") {
    p { 
        +"Here is "
        a("http://kotlinlang.org") { +"official Kotlin site" } 
    }
   //  sequence here
   doUl()
}  

I would assume some ‘wrapper’ function is going to be needed for ‘doUI()’. But I cannot yet see how to do something like this and any suggestions appreciated.


#2

You need to give this as a parameter to doUl() and then call li() on the object you supplied to the function.


#3

Thanks, that has given me a great stepping stone. The doUl should be doUl(this) makes sense and clicks thoughts into place. But the next challenge is the ‘fun doUl()’. What I am now thinking is needed is something like below, but with ‘Container’ replaced with the correct type. In this case the type would be ‘DIV’, but what is there a more generic type that would allow other containing HTML elements?? Again help appreciated!

fun doUl(container: Container){
    container.ul {
         li{  +"list item 1"}
         li{  +"list item n"}
   }
    
}

#4

Sorry, I’d simply use Intellij Idea to see the types/interfaces of the this object and then use one that fits. I have not much experience with HTML builders and no project where I could try this quickly.


#5

If you select ul block in the original code and call “Extract Function” refactoring you can get code like this:

private fun DIV.bar() {
    ul {
        li { +"list item 1" }
        li { +"list item n" }
    }
}

Next, if you want to get more generic type you can navigate to DIV declaration and find parent types. So, I think kotlinx.html.HTMLTag and kotlinx.html.HtmlBlockTag are good candidates to replace DIV here.