## A TODO List Example

Below is a TODO list composed from a JavaScript array using Scoped HTML, Scoped JS in combination with the HTML Partials API.

It features the ability to add/remove items. For the *remove* feature, we'd let the `<li>` element expose a *remover* button that the main `<ul>` logic can bind to the `removeItem()` method of the TODO application. For the *add* feature, we'd add a button to the TODO container that calls the `addItem()` method of the TODO application.

We've also decided to use [the Observer API](https://docs.web-native.dev/observer) and [PlayUI's `.itemize()`](https://docs.web-native.dev/play-ui/api/dom/itemize) method that provides a simple way to keep the list container in sync with application items.
 
[Check the live example here](https://web-native.dev/package/chtml/docs/demos/todo.html)

```html
<html>

    <head>

        <title>A TODO Example</title>
        <template name="items">
            
            <li namespace>
                <span scoped:id="desc"></span>
                <button scoped:id="remover">Remove</button>
                <script type="scoped">
                    this.namespace.desc.innerHTML = desc;
                </script>
            </li>

        </template>

    </head>

    <body>

        <div namespace id="todo">

            <h2 scoped:id="title"></h2>
            <ol scoped:id="items" template="items"></ol>
            <button scoped:id="adder">Add</button>
            <br />
            <br />
            <div>Ypu can also add items from the console. Open your console and type: <code>todoItems.push({desc:"New Item"})</code></div>

            <script type="scoped">
                this.namespace.title.innerHTML = title;
                $(this.namespace.items).itemize(items, (el, data, index, isUpdate) => {
                    el.bind(data);
                    $(el).attr('data-index', index);
                    if (!isUpdate) {
                        // This means el was newly generated by itemize()
                        el.namespace.remover.addEventListener('click', () => removeItem(el.getAttribute('data-index')));
                    }
                });
                this.namespace.adder.addEventListener('click', () => addItem());
            </script>

        </div>

        <script src="//unpkg.com/@web-native-js/observer/dist/main.js"></script>
        <script src="//unpkg.com/@web-native-js/play-ui/dist/main.js"></script>
        <script src="//unpkg.com/@web-native-js/chtml/dist/main.js"></script>
        <script>
            // Declare our tools
            let Obs = window.WN.Observer;
            let $ = window.WN.PlayUI;

            // Create the app
            let todo = {
                $,
                title: 'My TODO',
                items: [
                    {desc: 'Task-1'},
                    {desc: 'Task-2'},
                    {desc: 'Task-3'},
                ],
                addItem() {
                    window.todoItems.push({desc: prompt('Task description'),});
                },
                removeItem(index) {
                    window.todoItems.splice(index, 1);
                },
            };
            
            // Bind the app to the UI
            document.querySelector('#todo').bind(todo);

            // Make the items available globally
            // so that we can always manipulate them
            window.todoItems = Obs.proxy(todo.items);
        </script>
    </body>

</html>
```
