Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancing HTML Component design #38

Closed
bbodi opened this issue Jan 15, 2015 · 5 comments
Closed

Enhancing HTML Component design #38

bbodi opened this issue Jan 15, 2015 · 5 comments

Comments

@bbodi
Copy link
Collaborator

bbodi commented Jan 15, 2015

This is the idea behind class hierarchy - feel free to comment, we can change it:
Component trait just provide HTMLElement
ParentComponent provides some useful protected methods for manipulating element (add/remove child, attributes setting)
Content of HTML element is created by the Component code, not by the user of the component (TextInput, Grid, ...)
HTMLParentComponent
inner content of the html element can be created by DSL
example: div, span, ...

So If I undestand well, ParentComponents are the components which for we don't want to allow the user to add any kind of child elements explicitly. So for example the Grid: It is a table with many child elements, but these elements are added and controlled by the Grid itself, not the user of Grid, so she can't do like this:

Grid {...
   div {...} // It is prohibited for 'ParentComponents'
}

I think then that the name 'ParentComponent' is misleading.
In my opinion, we need only two base classes:

  • abstract Component class with the protected helper methods of ParentComponent.
    The classes that now are inherited from ParentComponent, would be the child of this Component.
    These child classes can control which elements can a user add to themselves.
  • HTMLParentComponent, but with an another name, e.g. "ComponentContainer", which for the user can freely add any elements (div, ul, etc.)
Can you use 4 spaces as indent?

Of course.

Was thinking about adding id and class as optional parameters to all HTML DSL functions, namely HTMLParentComponent.div an .span.
So that instead of 
div {
id = "bla"
ul { }
}
we can write 
div(id="bla") {
ul { }
}

I think it is a good Idead, but the default value should be an empty string.

@jean79
Copy link
Owner

jean79 commented Jan 15, 2015

Yep, that's what I meant.
Component as a trait only is quite useful - see class Spinner - the HTMLElement is provided by 3rd party Javascript library and not created by Kotlin code.
https://github.com/jean79/yested/blob/master/src/main/kotlin/net/yested/spin/spinner.kt

public class Spinner(val options:SpinnerOptions = SpinnerOptions()) : Component {

    private val jsSpinnerElement = createSpinner(createOptions()).spin().el

    private fun createOptions(): Any = object {
        ...
    }

    override val element: HTMLElement
        get() = jsSpinnerElement

}

But we can rename class hierarchy:
Component -> ComponentI
ParentComponent -> Component
HTMLParentComponent -> ComponentContainer

@bbodi
Copy link
Collaborator Author

bbodi commented Jan 15, 2015

Then the second difference is that ParentComponent creates its own Element, which fact is slightly hidden from the programmer (the name "ParentComponent" does not tell about it).

What about the following idea:
We would have a trait named Element, which receives a HTMLElement in his constructor.
This trait would contain all methods that works with HTMLElements, with a protected modifier.

The Grid and other classes that are inherited from ParentComponent would use this Element as their parents, like

public class Grid<T>(val columns:Array<Column<T>>) : Element(document.createElement("table") as HTMLElement) {

(Of course the createElement should be extracted to a method with a shorter name.)
It has the adventage that the Element creation is explicit for the programmer, who creates new constructs (like the Grid).

I know that the "Element" word is quite frequent (as well as the "Component"), but maybe it tells more about their function (I think "Component" means a bigger thing than "Element", especially in a HTML context)

@jean79
Copy link
Owner

jean79 commented Jan 15, 2015

I think we should keep ability to create HTMLElement later, like it is used in Spinner class. Putting all the logic into constructor might be lead to messy code.

I think it would be better to use Component name as it kind of encapsulate HTMLElement with some additiona logic (our code)

What about this:

public trait Component {
   val element:HTMLElement
}

public class Grid : Component {
   override val element = document.createElement("table") as HTMLElement
  //this is transparent for user -> he knows he must create an element, we can encapsulate into a method as you propose, like:
  //override val element = createDocumentHTMLElement("table")
}

//convenient class for simple extensible HTMLComponents
public open class HTMLComponent(name:String) : Component {
   override val element = createDocumentHTMLElement(name)
}

Maybe we do not need helper methods add,replace,fade. You are right that it hides from user what is really hapenning, what about making these extension methods of HTMLElement ? (if these are not there already)

@bbodi
Copy link
Collaborator Author

bbodi commented Jan 15, 2015

 Putting all the logic into constructor might be lead to messy code.

You are totally right.

What about this:

I like this version.

Maybe we do not need helper methods add,replace,fade.

I think they are useful and the Trait can contain them, just need some renaming for clarifications:

add(component:Component) -> appendChild
add(text:String) -> appendContent?
public fun replace(text:String) -> setContent? (most programmer is familiar "replace" from String.replace(pattern, newText), so using "replace" here is confusing)
public fun replace(component:Component) -> setChild? setContent?

Maybe these functions souldn't be open.

@jean79
Copy link
Owner

jean79 commented Jan 15, 2015

New method names looks good (last one would call setContent to match appendContent).
We can also add something like: clear() or removeAllChildren()
Let's keep them protected.

bbodi pushed a commit to bbodi/yested that referenced this issue Jan 19, 2015
bbodi pushed a commit to bbodi/yested that referenced this issue Jan 19, 2015
bbodi added a commit that referenced this issue Jan 19, 2015
Enhancing HTML Component design #38
@jean79 jean79 closed this as completed Jan 20, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants