Skip to content

How nested signals resolution should work? #140

@m-michalis

Description

@m-michalis

The bellow is a simple example of how i would expect (?) nested signals to work.

When clicking "to cart" it should change to "loading".

<html>
<body>
<div id="products"></div>
<script type="module">
    import {render, signal, html, effect, computed} from 'https://esm.run/uhtml/signal';

    class Cart {
        add(product) {
            console.log('adding to cart: ', product.name);
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('added to cart: ', product.name);
                    resolve();
                }, 2000);
            })
        }
    }

    const cart = new Cart();

    class Item {
        constructor(sData) {
            this.data = sData;
        }

        renderItem() {
            return html`
                <li>${this.data.value.name}
                    <button @click="${e => {
                        this.data.value.loading_cart = true
                        cart.add(this.data.value).then(() => {
                            this.data.value.loading_cart = false
                        });
                    }}">${this.data.value.loading ? 'loading' : 'to cart'}
                    </button>
                </li>`;
        }
    }

    class Catalog {
        #items = signal([]);
        #computed;
        #effect;

        constructor() {

            this.#computed = computed(() => this.#items.value.map(item => (new Item(signal(item))).renderItem()));
            this.#effect = effect(() => {
                render(document.getElementById('products'), () => html`
                    <ul>${this.#computed.value}</ul>`)
            });
        }

        addItem(value) {
            this.#items.value = [...this.#items.value, value];
        }

        setItems(items) {
            this.#items.value = items;
        }
    }

    const catalog = new Catalog();

    setTimeout(() => {
        catalog.setItems([
            {name: 'Shoes'},
            {name: 'T-Shirt'}
        ])
        setTimeout(() => {
            catalog.addItem({name: 'Hat'})
            catalog.addItem({name: 'Boots'})
        }, 1500)
    }, 500)


</script>
</body>
</html>

What would be a working example for the above?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions