npm package: @nathanfaucett/web_app
Description: Basic Web App for front-end web applications
Author: Nathan Faucett
Latest version: 0.1.22

# js-web_app-immutable

basic App for front-end web applications

# Cli

install web app for quick bootstrap [cli](https://gitlab.com/nathanfaucett/js-web_app-cli)

# App

the App holds all your apps stores and plugins, your apps state is stored with
[immutable.js](https://facebook.github.io/immutable-js/) data structures

```javascript
import { App } from "@nathanfaucett/web_app-immutable";
import config from "./config.json";

class YourApp extends App {
    constructor(config) {
        super(config);
    }
}

export default new YourApp(config);
```

## Stores

stores are views into you apps state

```javascript
import { List } from "immutable";
import app from "./app";

let ID = 0;

// uses immutable.fromJS internally to get initial state
const todos = app.createStore("todos", {
    list: []
});

todos.create = text => {
    let id = ID++;

    todos.updateState(state =>
        state.update("list", list => list.push(Map({ id: id, text: text })))
    );
};

todos.remove = id => {
    todos.updateState(prev => {
        return prev.update("list", list =>
            list.remove(list.findIndex(todo => todo.get("id") === id))
        );
    });
};

export default todos;
```

## Components

```javascript
import React from "react";
import connect from "@nathanfaucett/state-immutable-react";
import todos from "../stores/todos";
import app from "../app";
import Todo from "./Todo";

const todoListForm = app.createStore("todoListForm", {
    values: { text: "" },
    errors: { text: [] }
});

class TodoList extends React.Component {
    constructor(props) {
        super(props);

        this.form = app.createForm(
            {
                text: ({ onChange }) => ({
                    props: {
                        type: "text",
                        value: props.todoListForm.values.text,
                        onChange: e => onChange(e.target.value)
                    }
                })
            },
            {
                get: () => ({ ...this.props.todoListForm.values }),
                set: (errors, values) =>
                    todoListForm.setState({ errors, values })
            }
        );

        this.onDeleteTodo = id => {
            todos.remove(id);
        };
        this.onSubmit = e => {
            e.preventDefault();
            todos.create(this.props.todoListForm.values.text);
            this.form.reset();
        };
    }

    render() {
        const { values, errors } = this.props.todoListForm,
            fields = this.form.render(errors, values);

        return (
            <div className="TodoList">
                <form onSubmit={this.onSubmit}>
                    <input {...fields.text.props} />
                </form>
                <div>
                    {this.props.todos.list.map(todo => {
                        return (
                            <Todo
                                key={todo.id}
                                todo={todo}
                                onClick={this.onDeleteTodo}
                            />
                        );
                    })}
                </div>
            </div>
        );
    }
}

export default connect([todos, todoListForm])(TodoList);
```