developit / htm

Hyperscript Tagged Markup: JSX alternative using standard tagged templates, with compiler support.
Apache License 2.0
8.64k stars 169 forks source link

Object in props #216

Closed karolskolasinski closed 2 years ago

karolskolasinski commented 2 years ago
<!DOCTYPE html>
<html lang="en">
  <title>htm Demo</title>
  <script type="module">
    import { html, Component, render } from 'https://unpkg.com/htm/preact/standalone.module.js';

    class App extends Component {
      addTodo() {
        const { todos = [] } = this.state;
        this.setState({ todos: todos.concat(`Item ${todos.length}`) });
      }
      render({ page }, { todos = [] }) {
        return html`
          <div class="app">
            <${Header} name="ToDo's (${page})" />
            <ul>
              ${todos.map(todo => html`
                <li key=${todo}>${todo}</li>
              `)}
            </ul>
            <button onClick=${() => this.addTodo()}>Add Todo</button>
            <${Footer}>footer content here<//>
          </div>
        `;
      }
    }

    const Header = ({ name }) => html`<h1>${name} List</h1>`

    const Footer = props => html`<footer ...${props} />`

    render(html`<${App} page="All" />`, document.body);
  </script>
</html>

How can i pass an object as an attribute: render(html`<${App} page=${object} />`, document.body); Everything that you pass by html as an attribute in web components is a string, but maybe I doing something wrong.

developit commented 2 years ago

@karolskolasinski HTM doesn't use Web Components, object values are supported. To pass an object, use ${}:

let someObject = { foo: 'bar' };

// pass an object by reference:
html`<${Foo} value=${someObject} />`;

// pass an object literal:
html`<${Foo} value=${{ foo: 'bar' }} />`;

// spread an object to pass its properties as props:
html`<${Foo} ...${someObject} />`; // by reference
html`<${Foo} ...${{ foo: 'bar' }} />`; // object literal

In your example, the code you suggested should work as you described:

    class App extends Component {
      // <snip>
      render({ page }, { todos = [] }) {
        // `page` is whatever you passed - in this case, it's `object`.
        return html`
          <div class="app">
            <${Header} name="ToDo's (${page.name})" />
            ...
          </div>
        `;
      }
    }

    let object = { name: 'Page Name' };
    render(html`<${App} page=${object} />`, document.body);
developit commented 2 years ago

Closing since this seems like a question with an answer, but please re-open if I've missed something!