{"id":13447145,"url":"https://github.com/tamb/domponent","last_synced_at":"2025-09-03T14:32:40.244Z","repository":{"id":35013994,"uuid":"196616299","full_name":"tamb/domponent","owner":"tamb","description":"Build UI Components with the HTML You Already Have","archived":false,"fork":false,"pushed_at":"2023-03-04T05:39:49.000Z","size":39531,"stargazers_count":75,"open_issues_count":20,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-27T21:00:25.901Z","etag":null,"topics":["component-lifecycle","components","lifecycle-methods","react","stateless-components","stimulusjs"],"latest_commit_sha":null,"homepage":"https://tamb.github.io/domponent/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tamb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-07-12T17:09:37.000Z","updated_at":"2024-04-03T19:48:52.000Z","dependencies_parsed_at":"2024-01-18T15:58:10.616Z","dependency_job_id":"495164ce-f68b-451a-9a97-b6f1cd566269","html_url":"https://github.com/tamb/domponent","commit_stats":{"total_commits":419,"total_committers":5,"mean_commits":83.8,"dds":0.5632458233890214,"last_synced_commit":"f5eed13147ae8a023e82106619bf1b0737a1d1c0"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamb%2Fdomponent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamb%2Fdomponent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamb%2Fdomponent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamb%2Fdomponent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tamb","download_url":"https://codeload.github.com/tamb/domponent/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231895829,"owners_count":18442361,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component-lifecycle","components","lifecycle-methods","react","stateless-components","stimulusjs"],"created_at":"2024-07-31T05:01:09.359Z","updated_at":"2024-12-30T17:50:41.865Z","avatar_url":"https://github.com/tamb.png","language":"JavaScript","readme":"# 🔌\\\u003c/\u003e DOMponent\n\n**Build UI Components with the HTML You Already Have.**\n\u003cbr/\u003e\n**2kb gzipped and 6kb minified! 👌**\n\n\u003c!--\n[![](https://data.jsdelivr.com/v1/package/npm/domponent/badge)](https://www.jsdelivr.com/package/npm/domponent)\n[![](https://img.shields.io/npm/dw/domponent)](https://www.npmjs.com/package/domponent)\n--\u003e\n\n[![](https://img.shields.io/bundlephobia/minzip/domponent?color=green)](https://www.npmjs.com/package/domponent)\n[![](https://img.shields.io/github/license/tamb/domponent?color=informational)](https://www.github.com/tamb/domponent)\n[![](https://img.shields.io/npm/v/domponent)](https://www.npmjs.com/package/domponent)\n\n## How To:\n\n1. Drop a few `data` attributes into your existing HTML 💻\n\n```html\n\u003cdiv data-component=\"Counter\"\u003e\n  \u003cp data-bind=\"state:Counter.count\"\u003e0\u003c/p\u003e\n  \u003cbutton data-action=\"click-\u003eCounter.decrement\"\u003e\n    -1\n  \u003c/button\u003e\n  \u003cbutton data-action=\"click-\u003eCounter.increment\"\u003e\n    +1\n  \u003c/button\u003e\n\u003c/div\u003e\n```\n\n2. Write a JavaScript `class` component 🔌\n\n```js\nimport { Component } from \"domponent\";\n\nexport default class Counter extends Component {\n  constructor(el) {\n    super(el);\n  }\n\n  increment() {\n    this.setState({ count: this.state.count + 1 });\n  }\n\n  decrement() {\n    this.setState({ count: this.state.count - 1 });\n  }\n}\n```\n\n3. Initialize the App ⚡\n\n```js\nimport { Init } from \"domponent\";\nimport Counter from \"./Counter.js\";\n\nconst config = {\n  selector: document.getElementById(\"root\"),\n  components: {\n    Counter\n  },\n  appCreated: callbackFunction\n};\n\nnew Init(config);\n```\n\n**And you're good to go!!**\n\n\n## Checkout a practical example now:\nhttps://dev.to/tamb/modern-front-end-with-older-tech-625\n---\n\n## Docs 📖\n\n- [Purpose](#purpose-️)\n- [Demo](#demo-)\n- [Install](#install-)\n- [Data API](#data-API-)\n  - [data-component](#data-component)\n  - [data-bind](#data-bind)\n  - [data-action](#data-action)\n  - [data-state](#data-state)\n  - [data-ref](#data-ref)\n  - [data-ref-array](#data-ref-array)\n  - [data-key](#data-key)\n  - [data-props](#data-props)\n- [Extending the Component class](#extending-the-component-class-)\n- [Managing Component State](#managing-component-state-%EF%B8%8F)\n  - [Rendering HTML from Component State](#rendering-html-from-props-and-state)\n- [Lifecycle Methods](#lifecycle-methods-)\n- [Watchers](#watchers-)\n- [Stateless Components](#stateless-components-)\n- [Component Fields](#component-fields-)\n- [Init Function](#init-function-)\n- [Adding and Removing Components](#adding-and-removing-components-)\n- [Namespacing Data Attributes](#namespacing-data-attributes-)\n- [Custom Syntax](#custom-syntax-)\n- [Development Mode](#development-mode-)\n- [Syntax Examples](#syntax-examples-)\n- [Component Lifecycle](#component-lifecycle-%EF%B8%8F%EF%B8%8F)\n- [Contact](#contact-)\n\n### Purpose ✔️\n\n#### What does this do?\n\nThis library sets up a clean and modern way to turn prerendered HTML into UI components. You can easily implement some data-binding, handle scope, pass data around, and create components by using some of the conventions in this script. It's meant to be a very _very_ lightweight alternative to StimulusJS with a bit of a React flavor (lifecycle methods, props and component state).\n\n#### What does this library _not_ do?\n\nDOMponent does not handle client-side rendering out of the box, does not create virtual DOM, does not diff DOM (though it does diff state and props).\nIt's not meant to handle routing or entire application state. It's meant to take HTML fragments (Thymeleaf, Rails, Pug, whatever template engine you use) and create reusable functionality in the form of Components.\n\n#### Differences to KnockoutJS\n\nDOMponent is similar to Knockout in some ways:\n\n- it is template language-agnostic\n- the syntax looks similar\n- ... that's kinda about it.\n\nUnlike KnockoutJS, DOMponent:\n\n- is component-driven\n- has option for namespaced components\n- can isolate scope\n- is only 6kb (that's a 50kb savings)\n- is highly declarative\n- allows for highly specific DOM references\n- has lifecycle methods\n- performs insanely fast\n\n_Knockout_\n\nHTML\n\n```html\n\u003cp\u003eFirst name: \u003cinput data-bind=\"value: firstName\" /\u003e\u003c/p\u003e\n\u003cp\u003eLast name: \u003cinput data-bind=\"value: lastName\" /\u003e\u003c/p\u003e\n\u003ch2\u003eHello, \u003cspan data-bind=\"text: fullName\"\u003e \u003c/span\u003e!\u003c/h2\u003e\n```\n\nJS\n\n```js\nvar ViewModel = function(first, last) {\n  this.firstName = ko.observable(first);\n  this.lastName = ko.observable(last);\n\n  this.fullName = ko.pureComputed(function() {\n    return `${this.firstName()} ${this.lastName()}`;\n  }, this);\n};\n\nko.applyBindings(new ViewModel(\"Planet\", \"Earth\"));\n```\n\n_DOMponent_\n\nHTML\n\n```html\n\u003cdiv data-component=\"Hello\" data-state=\"{\"firstName\": \"Planet\", \"lastName\": \"Earth\"}\"\u003e\n  \u003cp\u003eFirst name: \u003cinput data-action=\"input-\u003eHello.setFirstName\" /\u003e\u003c/p\u003e\n  \u003cp\u003eLast name: \u003cinput data-action=\"input-\u003eHello.setLastName\"/\u003e\u003c/p\u003e\n  \u003ch2\u003eHello, \u003cspan data-bind=\"state:Hello.fullName\"\u003e \u003c/span\u003e!\u003c/h2\u003e\n\u003c/div\u003e\n```\n\nJS\n\n```js\nimport { Component } from \"domponent\";\n\nexport default class Hello extends Component {\n  constructor(conf) {\n    super(conf);\n  }\n\n  setFirstName(event) {\n    this.setState({ firstName: event.target.value }, () =\u003e {\n      this.setFullName();\n    });\n  }\n  setLastName(event) {\n    this.setState({ lastName: event.target.value }, () =\u003e {\n      this.setFullName();\n    });\n  }\n\n  setFullName() {\n    this.setState({\n      fullName: `${this.state.firstName} ${this.state.lastName}`\n    });\n  }\n}\n```\n\n\u003chr/\u003e\n \n### Demo 🤖\n\n[https://tamb.github.io/domponent/](https://tamb.github.io/domponent/)\n\nTodo List: https://codesandbox.io/embed/domponent-todo-with-undo-redo-sp3s2?fontsize=14\n\n**Local Demo** 😉\n\n1. `git clone` this repo\n2. `npm install`\n3. `npm run build:html-dev` or `npm run build:html-prod`\n\n\u003chr/\u003e\n\n### Install 📥\n\n#### npm\n\n```js\nnpm install --save domponent\n```\n\n**You can use an ES5 version by importing this file** `domponent/dist/domponent.es5.production.min.js`\n\nIf you're not using a transpiler, it's recommended to use the ES5 UMD. So here's the JSDelvr link:\n\n```js\n// production\n\u003cscript type=\"text/javascript\" src=\"https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.production.min.js\" defer\u003e\u003c/script\u003e\n\n// development\n\u003cscript type=\"text/javascript\" src=\"https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.development.min.js\" defer\u003e\u003c/script\u003e\n```\n\n\u003chr/\u003e\n\n### data API 💽\n\n**Note:** Use as much or as little of this library as you want.  You can use this for just `data-component`, `data-ref` and `data-ref-array` attributes and make your DOM selection a lot easier.  You can make stateless components with the `Exponent` class.  The sky's the limit.  At its core, Domponent is a set of utility classes for your HTML.\n\n#### `data-component`\n\nWe use this bad boy to match the component name to its corresponding `class` in the `Init` configuration object\n\nexample: if your HTML is `data-component=\"Counter\"` | you must have a component in your config called `Counter`\n\n#### `data-bind`\n\nBinds `state` or `props` to the `textContent` of an element\nFirst you specify if you want to bind `state` or `props` `data-bind=\"state:Counter.count\"` or `data-bind=\"props:Counter.count\"`\nThe left half of the `:` tells the component what object to bind to (state or props), the right half tells the component what key within the state or props to read from\n\n#### `data-action`\n\nBinds a DOM event with a component method.\nConsider the following:\n\n```html\n\u003cbutton data-action=\"click-\u003eCounter.increment\"\u003e\n  +1\n\u003c/button\u003e\n```\n\nThe left half of the `:` represents the literal string for the DOM event to listen for. The right half corresponds to the component method\n\nNote: You can add multiple listeners with a pipe `|`\nexample:\n\n```html\n\u003cbutton data-action=\"click-\u003eCounter.increment|mouseover-\u003eCounter.anotherMethod\"\u003e\n  +1\n\u003c/button\u003e\n```\n\nYou can pass `eventListener` options in as well. Options must be after a `.` after the class method. The options must be separated by a comma `,`.\n\n```html\n\u003cbutton\n  data-action=\"click-\u003eCounter.increment.passive,capture|mouseover-\u003eCounter.anotherMethod.once,passive\"\n\u003e\n  +1\n\u003c/button\u003e\n```\n\n#### `data-state`\n\nIf you want to instantiate your component with a particular state **in memory** you must attach a `data-state` attribute to the **root element** of the component\nexample:\n\n```\n\u003cdiv data-component=\"Counter\" data-state='{\"count\":24, \"isEven\": true}'\u003e\n  ...\n\u003c/div\u003e\n```\n\nThat's right. `data-state` takes any valid JSON object.\n\n#### `data-ref`\n\nIf you need to reference DOM elements, you can use `data-ref` like so:\n\n```html\n\u003cdiv data-ref=\"Counter.myElement\"\u003e\u003c/div\u003e\n```\n\nYou need to preface which component the element is on.\nIt is then stored in the components `$refs` object.\n\nYou can then access the element in `Counter` using `this.$refs.myElement` within the Component instance.\n\n#### `data-ref-array`\n\nYou can create an array of elements in your component this way:\n\n```html\n\u003cdiv data-ref-array=\"Counter.elements\"\u003e\u003c/div\u003e\n\u003cdiv data-ref-array=\"Counter.elements\"\u003e\u003c/div\u003e\n```\nIt is then stored in the components `$refs` object.\nYou can access the array of elements in your component with `this.$refs.elements`.\n\n#### `data-key`\n\nThis is totally optional. It's a _unique_ string for _each_ component instance.  \nThis is used internally to bind props. Therefore you must know the `$key` of the component you are receiving props from.\n\n```html\n\u003cdiv data-component=\"Counter\" data-key=\"aUniqueKey\"\u003e\n  ...\n\u003c/div\u003e\n```\n\nLet's say you're looping over this in your templating language. You should ensure your keys are unique.\n\n```html\n# for (let i=0; i\u003c10; i++){\n\u003cdiv data-component=\"Counter\" key=\"`aUniqueKey${i}`\"\u003e...\u003c/div\u003e\n}\n```\n\nIf you don't use this attribute, a unique key will be assigned to each component instance automatically. It can be accessed via `this.$key`\n\n#### `data-props`\n\nYou can share state from a parent component as `props` in a child component.\nThe markup would look like this\n\n```html\n\u003cdiv data-component=\"Counter\" key=\"parentCounter\"\u003e\n  \u003cdiv\n    data-props=\"myAwesomeProp\u003c-parentCounter:ofFive\"\n    data-component=\"DisplayAnything\"\n  \u003e\u003c/div\u003e\n\u003c/div\u003e\n```\n\nThe left side of the arrow `\u003c-` is the name of the prop in the `DisplayAnything` component.\nThe Right side of the arrow is `$key` of the parent component, a colon `:` and the name of the piece of `state` to inherit.\n\nYou can then use the lifecycle methods `propsWillUpdate` and `propsDidUpdate` to make changes within your child component.\n\n\u003chr/\u003e\n\n### Extending the `Component` class 📏\n\nLet's continue with Counter. The minimum js needed to create a component is below:\n\n```js\nclass Counter extends Component {\n  constructor(conf) {\n    super(conf);\n  }\n}\n```\n\n`super` adds the base methods and properties your component needs.\n\n\u003chr/\u003e\n\n### Managing Component State 🕹️\n\nDon't mutate the state directly. Call `this.setState`\n\n```js\nsetState(stateObject, callbackFunction);\n```\n\nThis is similar in concept to React's setState - although it's implemented differently.\n\nYou can add default states to your JS component and override them in the DOM\n\n```js\nexport default class Counter extends Component {\n  constructor(conf) {\n    super(conf);\n    this.state = {\n      count: parseInt(this.state.count) || 0,\n      isEven: this.state.count\n        ? this.state.count % 2 === 0\n          ? true\n          : false\n        : true,\n      stateFieldFromDOM: this.state.stateFieldFromDOM || \"default cat\",\n      stateFieldDefault: \"default iPhone 11\"\n    };\n    this.setState(this.state);\n  }\n```\n\n```\n\u003cdiv data-component=\"Counter\" data-state=\"{\"count\": 4, \"isEven\":true, \"stateFieldFromDOM\": \"some value here\"}\"\n```\n\nThe above state fields will override the default JS state fields.\n\n#### Rendering HTML from props and state\nThe value binding from `setState` will always be to `textContent`.  If you wish to use state/props to render HTML, you can add a watcher for that value and update the `$refs` node that will house the new HTML.  \n\n```js\nwatch(){\n   return {\n     count: {\n      post(newCount){\n        this.$refs.exclaimCount.innerHTML = `\u003cdiv class=\"uppercase\"\u003e${newcount}!\u003c/div\u003e`;\n      }\n     }\n   }\n}\n```\n\n\u003chr/\u003e\n\n### LifeCycle Methods 🌳\n\nThe following are methods you can use to access components at various points in their lifecycle\n\n| Lifecycle Method | Context            | Description                                                                                              |\n| ---------------- | ------------------ | -------------------------------------------------------------------------------------------------------- |\n| connecting       | Component/Exponent | Before the library wires up any of your Component/Exponent and you have access to other methods          |\n| connected        | Component/Exponent | After your Component/Exponent is wired up and all eventListeners are in place                            |\n| disconnecting    | Component/Exponent | Before removing eventListeners and deleting Component/Exponent from memory                               |\n| propsWillUpdate  | Component/Exponent | Before the props are updated within your component, no DOM mutations have happened                       |\n| propsDidUpdate   | Component/Exponent | After the props have updated and the DOM has changed                                                     |\n| stateWillUpdate  | Component          | Before the state of the current component or any of its dependents' props have changed                   |\n| stateDidUpdate   | Component          | Child components with inherited props have done their DOM manipulations and state and props have changed |\n\n\u003chr/\u003e\n\n### Watchers 👀\n\n`Component` and `Exponent` classes have a `watch` method that must return an object. Watchers allow you to hook into specific `state` or `props` value changes during the component lifecyle. This allows your state logic to be isolated instead of clumping it all in with `stateWillUpdate`, `stateDidUpdate`, `propsWillUpdate` or `propsDidUpdate`. This is meant to closely mimic watchers in `Vue.JS`.\n_Note_: Do NOT name your `state` and `props` fields the same.  This is bad practice and will break the watchers.\n\n```js\nwatch(){\n  return {\n    myField: {\n      pre(newValue, oldValue){\n        // my logic\n      },\n      post(newValue){\n        // my logic\n      }\n    }\n  }\n}\n```\n\nYou can view your watched state fields in the components `$watchers` object.\n\n\n\u003chr/\u003e\n\n### Stateless Components 😐\n\nExtend the `Exponent` class to create a component with _only_ `props`\nThis is slightly lighterweight than a `Component`. Quicker to wire up and takes up less memory.\n\n```\nimport { Exponent } from 'domponent'\n\nclass StatelessThing extends Exponent{\n  constructor(conf){\n    super(conf);\n  }\n}\n```\n\nYou will then only have access to:\n\n- `propsWillUpdate`\n- `propsDidUpdate`\n\n**Why `Exponent`??**  \n\u003cbr/\u003e\nBecause it simply interprets or _expounds_ the data that it is given... and it sounds like Component.\n\n\u003chr/\u003e\n\n### Component Fields 🌵\n\nComponents or Exponents will be given the following fields.\n\n| Field Name | Type    | Access  | Context            | Description                                         |\n| ---------- | ------- | ------- | ------------------ | --------------------------------------------------- |\n| \\$app      | object  | public  | Component/Exponent | The entire Domponent application                    |\n| \\$b        | array   | private | Component/Exponent | eventListener bindings for internal use             |\n| \\$d        | object  | private | Component          | The parent components references to its children    |\n| \\$key      | string  | public  | Component/Exponent | Unique identifier for the component instance        |\n| \\$name     | string  | public  | Component/Exponent | The name of the component type                      |\n| \\$p        | object  | private | Component/Exponent | Internal collection of props and its DOM references |\n| props      | object  | public  | Component/Exponent | Key/Value pairs of data passed                      |\n| \\$root     | element | public  | Component/Exponent | The root DOM Node of the component                  |\n| \\$s        | object  | private | Component          | Internal collection of state and its DOM references |\n| state      | object  | public  | Component          | Key/Value pairs of data which can be updated        |\n| $watchers  | object  | public  | Component          | stored change functions and their respective state and prop key |\n\n\u003chr/\u003e\n\n### `Init` function 🏇\n\nThis function creates the app and registers all the components. This takes a `config` object as required argument:\n\n```js\nconst config = {\n  selector: document.getElementById(\"root\"),\n  components: { Counter },\n  appCreated: callbackFunction\n};\n\nconst App = new Init(config);\n```\n\nIt then exposes the following methods:\n\n- createComponent\n- deleteComponent\n- register\n- unregister\n\nAnd the following objects:\n\n- component - all base classes for components in the app\n- createdComponents - all instances of app components\n\nYou can also exclude the `components` object of the configuration and create an app without any components to begin with.\n\n  \u003chr/\u003e\n\n### Adding and removing components 🤼\n\n#### Adding components\n\n##### `createComponent`\n\n@params:\n\n- {Element} a DOM element to create the component instance\n- {Function} optional callback function\n\n```js\nApp.createComponent(document.getElementById(\"added-html\"), callback);\n```\n\n##### `register`\n\n@params\n\n- {Component} a component definition\n- {Function} optional callback function\n\n```js\nApp.register(NewComponent, callback);\n```\n\n#### Deleting components\n\n##### `deleteComponent`\n\n@params:\n\n- {String} - key of the component _instance_ you want to delete, can be assigned via `data-key` or accessed inside component via `this.$key`\n- {Function} optional callback function\n\n```js\nApp.deleteComponent(\"my-component-instance-key\", callback);\n```\n\n##### `unregister`\n\n@params:\n\n- {String} - The name of the key you used to register your component on app Init.\n- {Function} optional callback function\n\n```js\nApp.unregister(\"NewComponent\", callback);\n```\n\n  \u003chr/\u003e\n\n### Namespacing data attributes 📇\n\nTo avoid `data-` attributes clashing with other selectors, libraries, etc. you can override the default attribute names in the app config object:\n\n```js\nInit({\n  selector: getElementById('root),\n  components: { Counter },\n  dataAttributes: {\n    component: 'mynamespace-component',\n    state: 'cool-state',\n  }\n});\n```\n\nThis means that your HTML will look like this:\n\n```html\n\u003cdiv data-mynamespace-component=\"Counter\" data-cool-state='{\"count\":12}'\u003e\n  ...\n\u003c/div\u003e\n```\n\n\u003chr/\u003e\n\n### Custom Syntax 🔧\n\nYou can optionally customize the syntax you use in your HTML.\nThe following items can be customized.\n\n    INHERITS_FROM: '\u003c-',\n    FROM_COMPONENT: '.',\n    KEY_VALUE: ':',\n    MULTIPLE_VALUES: \"|\",\n    METHOD_CALL: \"-\u003e\",\n    LIST: \",\"\n\nThis means that in your config you can add:\n\n```js\n{\n   customSyntax: {\n      LIST: \"!\",\n      METHOD_CALL: \"#\"\n  }\n}\n```\n\nAnd your HTML can use this!\n\n\u003chr/\u003e\n\n### Development Mode 🤓\n\nWhen developing with Domponent, using the development build adds helpful errors and logs\nto your console from Development Dom (this guy-\u003e) 🤓\n\nThe easiest way to use this is with Webpack Aliases:\n\n```js\nresolve: argv.mode === 'development'? {\n      alias: {\n        domponent: 'domponent/dist/domponent.development.js'\n      }\n    }: {},\n\n```\n\nThis way your development build of webpack will swap out the production version of Domponent for the version sprinkled with help from Dom.\n\n\u003chr/\u003e\n\n### Syntax Examples 🔤\n\nYou can write your component HTML for various templating engines and _include_ them as partials/fragments/whatever your engine refers to as \"chunks of HTML\".\n\nHere are some examples of how you might use Domponent.\n\n**Note:** Despite these syntax differences in the markup, remember that the component is simply a JS class ✌️\n\n**Pug Syntax Example** 🐶\n\n```js\n// counter.pug\nmixin counter(count)\n div(data-component=\"Counter\" data-state=`\n    {\n      \"count\": count,\n      \"isEven\": count % 2 === 0\n    }\n  `)\n   p(data-bind=\"state:Counter.count\") #{count}\n   button(data-action=\"click-\u003eCounter.increment\") +1\n   button(data-action=\"click-\u003eCounter.decrement\") -1\n\n// usage\n+counter(101119)\n+counter(61316)\n```\n\n**Thymeleaf Syntax Example** 🍃\n\n```html\n// counter.html\n\u003cdiv\n  data-component=\"Counter\"\n  th:fragment=\"Counter\"\n  th:data-state='|{\"count\":${count}, \"isEven\": ${count % 2 == 0}}|'\n\u003e\n  \u003cp data-bind=\"state:Counter.count\" th:text=\"${count}\"\u003e\u003c/p\u003e\n  \u003cbutton data-action=\"click-\u003eCounter.increment\"\u003e\n    +1\n  \u003c/button\u003e\n  \u003cbutton data-action=\"click-\u003eCounter.decrement\"\u003e\n    -1\n  \u003c/button\u003e\n\u003c/div\u003e\n\n// usage\n\u003cth:block th:replace=\"./counter.html  :: Counter(count: 1289)\" /\u003e\n\u003cth:block th:replace=\"./counter.html  :: Counter(count: 491)\" /\u003e\n```\n\n**Razor Syntax Example** ⚔️\ncoming soon...\n\n\u003c!--\n```html\n// counter.html\n\u003cdiv data-component=\"Counter\"\u003e\n  \u003cp\n    data-bind=\"state:Counter.count\"\n    data-state='{\"count\":@(count), \"isEven\": @(count % 2 == 0)}'\n  \u003e\n    @count\n  \u003c/p\u003e\n  \u003cbutton data-action=\"click-\u003eCounter.increment\"\u003e\n    +1\n  \u003c/button\u003e\n  \u003cbutton data-action=\"click-\u003eCounter.decrement\"\u003e\n    -1\n  \u003c/button\u003e\n\u003c/div\u003e\n```\n--\u003e\n\n**Ruby on Rails Syntax Example** 💎\ncoming soon...\n\n**Mustache Syntax Example** 👺\ncoming soon...\n\n\u003chr/\u003e\n\n### Component Lifecycle 🕵️‍♂️\n\n![updating component](https://raw.githubusercontent.com/tamb/domponent/master/domponent-lifecycle.jpg)\n\n### Contact 🤙\n* Email:  `domponent [at] gmail [dot] com` (*Please use the subject `Domponent Support` or we will not respond*)\n* Twitter: `@domponent`\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftamb%2Fdomponent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftamb%2Fdomponent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftamb%2Fdomponent/lists"}