Skip to content

herrmanno/piece-of-cake

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PieceOfCake

JavaScript like it should be

Install

npm install piece-of-cake

or just include a script tag, like

<script src="https://unpkg.com/piece-of-cake"></script>

  1. Define your html like ever:
<body>
    <input placeholder="what to to next?"/>
    <button onclick="addTodo" disabled>Add</button>
    <ul><!-- todo entries shall go here --></ul>

    <script>
        // functions like 'addTodo' and 'onChangeFilter' go here
    </script>
</body>
  1. Extract your event handling functions into there own scope, where they belong:
class MyControllerClass {

     addTodo() {
        const input = document.getElementsByTagName("input")[0]
        const list = document.getElementsByTagName("ul")[0]
        const value = input.value        
        const li = document.createElement("li")
        li.innerText = value
        list.apendChild(li)        
    }
    
}
  1. Extend the PieceOfCake Controller to get access to some useful helper methods (this is optional)
class MyControllerClass extends PieceOfCake.Controller {
    //...
}
  1. Simplify bindings to dom elements you need to access in your event handlers
    <input placeholder="what to to next?"/>
    <button onclick="addTodo" disabled>Add</button>
    <ul data-id="todolist">
        <!-- use a standard data tag here. Nothing special. No Side-effects -->
    </ul>
class MyControllerClass extends {

    get input() {
        return this.find("input")
    }

    get list() {
        return this.findByDataID("todolist")
    }

    addTodo() {
       // ...
    }
    
}
  1. Store your state in its own field, where it belongs:
class MyControllerClass extends {

    get todos() {
        return this._todos || [] // 'this._todos' is a kind of backing field. Nothing special. Just JavaScript
    }

    set todos(value) {
        this._todos = value
    }

    addTodo() {
       // ...
       this.todos = [this.todos, text]
       // ... update todo <ul>
    }
    
}
  1. Connect your rendering logic to methods that update your state to keep your controller clean
class MyControllerClass extends {

    set todos(value) {
        this._todos = value
        this._renderTodos()
    }

    addTodo() {
       this.todos = [this.todos, text]
    }

    _renderTodos() {
        this.list.innerHTML = ""
        this.todos.forEach(text => {
            const li = document.createElement("li")
            li.innerText(text)
            this.list.appendChild(li)
        })
    }
    
}
  1. Make your controller class visible to the library and connect it to a specific sub-tree of your dom it should control
PieceOfCake.controllerClasses.push(MyControllerClass)
    <body data-controller="MyControllerClass">
        <!-- Nothing special with the data-attribute. But you must call it 'controller', otherwise the library won't find it-- >
    </body>
  1. Use optional field and element binding shorthands in your controller
class MyControllerClass extends {
    static elements = {
        input: "input",     // this will bind 'this.input' to an element w/ data-id="input"
        list: "todolist"
    }

    static fields = {
        todos: {                    // this will create a getter and setter for the field 'todos'
            defaultValue: [],       // it creates a backing field w/ default Value []
            set(value) {            // define custom behavour after the backing field was updated here
                this._renderTodos
            }
        }
    }
}

Example

Just look at the basic or advanced example script to get an idea of how things work.

About

JavaScript like it should be.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published