Skip to content

2. Creating Component

NotElementImport edited this page Nov 10, 2024 · 2 revisions

Base

The framework works through components that contain the layout, and the logic to work with the interface.

Example of a simple component:

import { comp } from "horizon-core/component";

export default comp((_, { text }) => {
    text('Hello world!')
})

And the output will be

<span>
    Hello world!
</span>

The principle of operation is similar to html only using js

A more severe example:

import { comp } from "horizon-core/component";

export default comp((_, { $, text }) => {
    // News block
    $('div', { class: 'app-news' }, () => {
        // News title
        $('header', { class: 'app-news__title' }, () => {
            text('Neque porro quisquam est qui...')
        })
        // News content
        $('main', { class: 'app-news__content' }, () => {
            text('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque nec nisl sapien. Nulla vehicula...')
        })
        // News footer
        $('footer', { class: 'app-news__footer' }, () => {
            text('Author: Jonh Jr. Doe')
        })
    })
})

And the output will be

<div class="app-news">
    <header class="app-news__title">
        Neque porro quisquam est qui...
    </header>
    <main class="app-news__content">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque nec nisl sapien. Nulla vehicula...
    </main>
    <footer class="app-news__footer">
        Author: Jonh Jr. Doe
    </footer>
</div>

Simple features

Let's make the news list auto-generated. Let's use the same structure, but expand the possibilities

// Using TypeScript in this example
import { comp } from "horizon-core/component";

interface IArticle {
    title: string
    content: string
    author: string
}
// News block
const articleComponent = comp<IArticle>((props, { $, text }) => {
    $('div', { class: 'app-news' }, () => {
        $('header', { class: 'app-news__title' }, () => {
            text(props.title)
        })
        $('main', { class: 'app-news__content' }, () => {
            text(props.content)
        })
        $('footer', { class: 'app-news__footer' }, () => {
            text(`Author: ${props.author}`)
        })
    })
})
// Main component (News list)
export default comp((_, { use }) => {
    const news = [
        { title: 'Test 1', content: 'This is first article', author: "Jonh Jr. Doe" },
        { title: 'Test 2', content: 'This is article for example', author: "Jonh Sr. Doe" }
    ]

    for (const article of news) {
        use(articleComponent, article)
    }
})

In this example, we used TypeScript for typing. We also used the renderer of the internal component. For rendering we used use() method (atom), for rendering articleComponent. In the output we get this html:

<div class="app-news">
    <header class="app-news__title">
        Test 1
    </header>
    <main class="app-news__content">
        This is first article
    </main>
    <footer class="app-news__footer">
        Author: Jonh Jr. Doe
    </footer>
</div>
<div class="app-news">
    <header class="app-news__title">
        Test 2
    </header>
    <main class="app-news__content">
        This is article for example
    </main>
    <footer class="app-news__footer">
        Author: Jonh Sr. Doe
    </footer>
</div>

see also Reactivity and Dynamic render

Clone this wiki locally