wbijker / spwa-php

A Server-Powered Web Applications (SPWA) framework using PHP.
0 stars 0 forks source link

Render function alternative #7

Open wbijker opened 9 months ago

wbijker commented 9 months ago

I don't like custom templating languages. Primary for its lack of type safety. And off course the extra compilation step.

What about a strongly typed render function? Just like we have in almost all functional languages.

 private function render(HomePage $model): TemplateNode
    {

        return div([
            script(src("https://cdn.tailwindcss.com")),
            input(type("text"), value($model->text), bound("text")),
            button(click(0), ["Reset action"]),
            div([
                "Counter: $model->counter"
            ]),

            $this->renderOtherStuff(),

            button(click(fn() => $model->inc(1)), ["Increment")]),
            button(click(fn() => $model->inc(-1)), ["Decrement")]),
            button(click(fn() => $model->sync()), ["Sync"]),

            ul([
                for_($model->list, fn($list, $index) => li(click(fn() => $model->remove($index)), [$list]))
            ]),

            div(class_(classNames("p-4 m-4 border border-gray-600", $model->counter % 2 == 0 ? 'bg-red-500' : 'bg-blue-500')), [
                "Odd "
            ]),
        ]);
wbijker commented 8 months ago

With the use of a union variadic type we can combine attributes and nodes to give us a clear and concise syntax .


class Attribute {}
class Tag {}

function _class(string $value): Attribute {
    return new Attribute();
}

/**
 * @param (Attribute|Tag) ...$args
 * @return Tag
 */
function div(...$args): Tag {
    return new Tag('div', ...$args);
}

function text(string $value): Tag {
    return new Tag();
}

$node = div(_class("mx-10"), 
    div(_class("p-2"), 
        text("some text")
    )
);
wbijker commented 8 months ago

class is almost always used. Make it a optional first argument

/**
 * @param string|null $class
 * @param (Attribute|Tag) ...$args
 * @return Tag
 */
function div(?string $class = null,, ...$args): Tag {
    return new Tag('div', ...$args);
}

$node = div("mx-10",
    div("p-2",
        text("some text")
    )
);