{"_id":"@ember-paper-lite/ember-composability-tools","_rev":"3-d9b188a4878f4813297c6ed2e7de51cd","name":"@ember-paper-lite/ember-composability-tools","dist-tags":{"latest":"0.0.15"},"versions":{"0.0.13":{"name":"@ember-paper-lite/ember-composability-tools","version":"0.0.13","description":"Helpers for building a somewhat different kind of components.","keywords":["ember-addon","composability","utilities"],"repository":{"type":"git","url":"git+https://github.com/xud6/ember-composability-tools.git"},"license":"MIT","author":{"name":"xud6"},"directories":{"doc":"doc","test":"tests"},"scripts":{"build":"ember build --environment=production","lint":"npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'","lint:fix":"npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix","lint:hbs":"ember-template-lint .","lint:hbs:fix":"ember-template-lint . --fix","lint:js":"eslint . --cache","lint:js:fix":"eslint . --fix","start":"ember serve","test":"npm-run-all lint test:*","test:ember":"ember test","test:ember-compatibility":"ember try:each"},"dependencies":{"ember-cli-babel":"^7.23.0","ember-cli-htmlbars":"^5.3.1","ember-in-element-polyfill":"^0.2.0"},"devDependencies":{"@ember/optional-features":"^2.0.0","@ember/test-helpers":"^2.1.4","@glimmer/component":"^1.0.3","@glimmer/tracking":"^1.0.3","babel-eslint":"^10.1.0","broccoli-asset-rev":"^3.0.0","ember-auto-import":"^1.10.1","ember-cli":"~3.24.0","ember-cli-dependency-checker":"^3.2.0","ember-cli-fastboot":"2.1.1","ember-cli-inject-live-reload":"^2.0.2","ember-cli-sri":"^2.1.1","ember-cli-terser":"^4.0.1","ember-disable-prototype-extensions":"^1.1.3","ember-export-application-global":"^2.0.1","ember-load-initializers":"^2.1.2","ember-maybe-import-regenerator":"^0.1.6","ember-page-title":"^6.0.3","ember-qunit":"^5.1.1","ember-resolver":"^8.0.2","ember-sinon":"^4.0.0","ember-source":"~3.24.0","ember-source-channel-url":"^3.0.0","ember-template-lint":"^2.15.0","ember-try":"^1.4.0","eslint":"^7.17.0","eslint-config-prettier":"^7.1.0","eslint-plugin-ember":"^10.1.1","eslint-plugin-node":"^11.1.0","eslint-plugin-prettier":"^3.3.1","loader.js":"^4.7.0","npm-run-all":"^4.1.5","prettier":"^2.2.1","qunit":"^2.13.0","qunit-dom":"^1.6.0"},"engines":{"node":"10.* || >= 12"},"ember":{"edition":"octane"},"ember-addon":{"configPath":"tests/dummy/config"},"gitHead":"d8bfc1e77e9e157b2ea0ba1e9b2324f03770a1e8","bugs":{"url":"https://github.com/xud6/ember-composability-tools/issues"},"homepage":"https://github.com/xud6/ember-composability-tools#readme","_id":"@ember-paper-lite/ember-composability-tools@0.0.13","_nodeVersion":"14.17.5","_npmVersion":"6.14.14","dist":{"integrity":"sha512-E/6B0duITpClJXUeS8jU4TeJROq8KAgRR/4FlkZZRYifrLwvYAar5hJFpVvGfQQ/Ky7fTrMe35JMY4KyDaH4vg==","shasum":"b301b463950f8e2f807965bd38148a19238867ce","tarball":"https://registry.npmjs.org/@ember-paper-lite/ember-composability-tools/-/ember-composability-tools-0.0.13.tgz","fileCount":12,"unpackedSize":17556,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhHdB8CRA9TVsSAnZWagAA8BcP/1iT7YhoRC7aEdrWWfjP\nuTaKJJljqFx8rEyga3pHXhIrAB8N8kzBHZRmk9qa4LZ/bu/5CQQ3ti/a13Vv\nUjC5qG80VW8jCy5dBF+7OR5yteMY9vh+qrrbr6G4y2/UpSLwdqxJNbi4bLqz\nzyUhk884bsjghpZbiw7DfLShhewVPq+6mdPDZN2tR8OD2/oeloxfh5X2q5/0\nslV7/VTrnPJZPSZzwXfAz8SmZciCy0R9MDfa6lKTJ7dLMOzPW30g529dzdHF\ntfbK9yfkcPVx+vgjcUVwSJGHoqXBUld81oIFyn+pbIKzXqf8qztEqboGeGDa\n/xUhLC9MdATgHrQKIXDkheiVcWBp1zrJiXekmsBTVagUID+1PoY95UW6yZBx\nLR0dY4dUsTSECv3U9gEVXCh8B7tW5+nHT29k/IjLW+rfMCe0pvJ0pvlTjVhw\nGHLiWdf8U1hfzhkgCN8NifZEHJ/z0ScOdAXDmQhMZbbepMCeNuJx0IFcr/Mt\nW4yBOhaxA6eUIU/4UaM/Nsqc4XeWW6f7MzIbDKOBrWluY06WeFL2srWLVWMQ\nAYGxlD3ZtPuW1/0SEZXF+7c9rV8GJTB/2RubTS0WJ6M0v3ZHItFLkHl8LuTE\nwNULuICRwbfFfgrodUxGB9vYMHQ+EEcd8OwTUKz97UT9x1F0DyxU/pBQR2E6\nCPeb\r\n=Ec2T\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCuPXMQwT+se9N3ahWJ+4JbY7yOBNmn7VcAc1zEncgovgIgLJ7YINvSBC8ldRBz4uwsGo1hxByhDIhK9H4SrcbLgeU="}]},"_npmUser":{"name":"xud6","email":"admin@xdq.me"},"maintainers":[{"name":"xud6","email":"admin@xdq.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ember-composability-tools_0.0.13_1629343867871_0.9619932640679136"},"_hasShrinkwrap":false},"0.0.14":{"name":"@ember-paper-lite/ember-composability-tools","version":"0.0.14","description":"Helpers for building a somewhat different kind of components.","keywords":["ember-addon","composability","utilities"],"repository":{"type":"git","url":"git+https://github.com/xud6/ember-composability-tools.git"},"license":"MIT","author":{"name":"xud6"},"directories":{"doc":"doc","test":"tests"},"scripts":{"build":"ember build --environment=production","lint":"npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'","lint:fix":"npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix","lint:hbs":"ember-template-lint .","lint:hbs:fix":"ember-template-lint . --fix","lint:js":"eslint . --cache","lint:js:fix":"eslint . --fix","start":"ember serve","test":"npm-run-all lint test:*","test:ember":"ember test","test:ember-compatibility":"ember try:each"},"dependencies":{"ember-cli-babel":"^7.23.0","ember-cli-htmlbars":"^5.3.1","ember-in-element-polyfill":"^0.2.0"},"devDependencies":{"@ember/optional-features":"^2.0.0","@ember/test-helpers":"^2.1.4","@glimmer/component":"^1.0.3","@glimmer/tracking":"^1.0.3","babel-eslint":"^10.1.0","broccoli-asset-rev":"^3.0.0","ember-auto-import":"^1.10.1","ember-cli":"~3.24.0","ember-cli-dependency-checker":"^3.2.0","ember-cli-fastboot":"2.1.1","ember-cli-inject-live-reload":"^2.0.2","ember-cli-sri":"^2.1.1","ember-cli-terser":"^4.0.1","ember-disable-prototype-extensions":"^1.1.3","ember-export-application-global":"^2.0.1","ember-load-initializers":"^2.1.2","ember-maybe-import-regenerator":"^0.1.6","ember-page-title":"^6.0.3","ember-qunit":"^5.1.1","ember-resolver":"^8.0.2","ember-sinon":"^4.0.0","ember-source":"~3.24.0","ember-source-channel-url":"^3.0.0","ember-template-lint":"^2.15.0","ember-try":"^1.4.0","eslint":"^7.17.0","eslint-config-prettier":"^7.1.0","eslint-plugin-ember":"^10.1.1","eslint-plugin-node":"^11.1.0","eslint-plugin-prettier":"^3.3.1","loader.js":"^4.7.0","npm-run-all":"^4.1.5","prettier":"^2.2.1","qunit":"^2.13.0","qunit-dom":"^1.6.0"},"engines":{"node":"10.* || >= 12"},"ember":{"edition":"octane"},"ember-addon":{"configPath":"tests/dummy/config"},"gitHead":"60bd9575a1cbdb2be8004f6fb8c96c7631883b96","bugs":{"url":"https://github.com/xud6/ember-composability-tools/issues"},"homepage":"https://github.com/xud6/ember-composability-tools#readme","_id":"@ember-paper-lite/ember-composability-tools@0.0.14","_nodeVersion":"14.17.5","_npmVersion":"6.14.14","dist":{"integrity":"sha512-jDEjmSIj/VwcaU6xXDbqsZbBYjpIwNZlz0EVtHObioawv60n7cZQzJNS8I7s3fiH85+GqXZ+GwDLJeVEVO5MGg==","shasum":"7b857d80a73f6bb26ae43651bf6f4149ae31d016","tarball":"https://registry.npmjs.org/@ember-paper-lite/ember-composability-tools/-/ember-composability-tools-0.0.14.tgz","fileCount":12,"unpackedSize":17556,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhHdLKCRA9TVsSAnZWagAAJc8P/RVyEtMpJ9e79WCFUKgI\nk3Ih2i/s2o+IAbZviqVMrHIOfRSOwEOpezbT5qgZ2SgV5UuU82gl3GUk7u8Z\nNKBBJLpl2lx/llrQ7H4Idfxu/O7LaoRxSrtB60ucpbiqlSquLCR2q6Jmu73d\npJe7Pwof9LCJCQSFMb6lrSYzoCei+iHWOXYozcAwHjglfnYwJT16UEDtYZ2t\ntsDcJfYkC065END/ujvnQHFDz2nuu6ftiRqTBQayLauaRqP0QpJxLOhTFDlJ\n+x016wrun0DNqJd3sFFZ0ScfB8QAhBMFfNJ5agRMDJ+rHQJcS00hUP9HU439\nKi7Bqa4fTPpwAuYDflnz294Kjsa9TzAaMOCxyBO7fNJ0wsmH+VvMg2zt/N53\nGl+pkX7X0odk2cIulRUPrxuOM/OhO1z/gEXthO2ypDb7lbDSCLHqEHrpavk1\nmcdF5h7iZRh+1ojkIwPIq2ot3JhmDlOeowvHh+vKKCbxyVkcMFEl79N14hZ7\n0P7rE9Oqdn9KtkUjNQj9Fw/mtUv3PYYIS3FhnYWLFTfaBUx/w0lbDRN/fDgE\nCjfA/XFmTXIm2jFVyrkg3CdYincmz0pGWdpZPYjRME4aT0z0vwUcAShXUnYk\nZGuOKr3/tDjggI3wrnJVdx2qPXzVJIMjGZu+5YRsL9m/mylBZ3lMNvmpYf2z\nLaia\r\n=fY+7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICLWktIOv3Mr1Wikc2Nz5ez29PUXC7/HZxBDKwSvlv0cAiAUOOOBWYk9J6kva5jsok9RA4W3PGPpT1QkhUn2cEAmdw=="}]},"_npmUser":{"name":"xud6","email":"admin@xdq.me"},"maintainers":[{"name":"xud6","email":"admin@xdq.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ember-composability-tools_0.0.14_1629344458268_0.7321433306648186"},"_hasShrinkwrap":false},"0.0.15":{"name":"@ember-paper-lite/ember-composability-tools","version":"0.0.15","description":"Helpers for building a somewhat different kind of components.","keywords":["ember-addon","composability","utilities"],"repository":{"type":"git","url":"git+https://github.com/xud6/ember-composability-tools.git"},"license":"MIT","author":{"name":"xud6"},"directories":{"doc":"doc","test":"tests"},"scripts":{"build":"ember build --environment=production","lint":"npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'","lint:fix":"npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix","lint:hbs":"ember-template-lint .","lint:hbs:fix":"ember-template-lint . --fix","lint:js":"eslint . --cache","lint:js:fix":"eslint . --fix","start":"ember serve","test":"npm-run-all lint test:*","test:ember":"ember test","test:ember-compatibility":"ember try:each"},"dependencies":{"ember-cli-babel":"^7.23.0","ember-cli-htmlbars":"^5.3.1","ember-in-element-polyfill":"^0.2.0"},"devDependencies":{"@ember/optional-features":"^2.0.0","@ember/test-helpers":"^2.1.4","@glimmer/component":"^1.0.3","@glimmer/tracking":"^1.0.3","babel-eslint":"^10.1.0","broccoli-asset-rev":"^3.0.0","ember-auto-import":"^1.10.1","ember-cli":"~3.24.0","ember-cli-dependency-checker":"^3.2.0","ember-cli-fastboot":"2.1.1","ember-cli-inject-live-reload":"^2.0.2","ember-cli-sri":"^2.1.1","ember-cli-terser":"^4.0.1","ember-disable-prototype-extensions":"^1.1.3","ember-export-application-global":"^2.0.1","ember-load-initializers":"^2.1.2","ember-maybe-import-regenerator":"^0.1.6","ember-page-title":"^6.0.3","ember-qunit":"^5.1.1","ember-resolver":"^8.0.2","ember-sinon":"^4.0.0","ember-source":"~3.24.0","ember-source-channel-url":"^3.0.0","ember-template-lint":"^2.15.0","ember-try":"^1.4.0","eslint":"^7.17.0","eslint-config-prettier":"^7.1.0","eslint-plugin-ember":"^10.1.1","eslint-plugin-node":"^11.1.0","eslint-plugin-prettier":"^3.3.1","loader.js":"^4.7.0","npm-run-all":"^4.1.5","prettier":"^2.2.1","qunit":"^2.13.0","qunit-dom":"^1.6.0"},"engines":{"node":"10.* || >= 12"},"ember":{"edition":"octane"},"ember-addon":{"configPath":"tests/dummy/config"},"gitHead":"eae3b93ccc4124c6d5063c0461f2d672200b7f68","bugs":{"url":"https://github.com/xud6/ember-composability-tools/issues"},"homepage":"https://github.com/xud6/ember-composability-tools#readme","_id":"@ember-paper-lite/ember-composability-tools@0.0.15","_nodeVersion":"14.17.5","_npmVersion":"6.14.14","dist":{"integrity":"sha512-o3rEcMveOwjshy4m4b28srkdOr+Y+B86+ZR8iPN+6pdamGZ8t/X0ubCZ1mCcRUGl5Y45lYiVqUnDamGpKvLPJQ==","shasum":"c55f3bb8b2a4d9f52d1e3783f6e68182f22d8532","tarball":"https://registry.npmjs.org/@ember-paper-lite/ember-composability-tools/-/ember-composability-tools-0.0.15.tgz","fileCount":12,"unpackedSize":17556,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhHdRdCRA9TVsSAnZWagAAI5oP/A1d3T47jDj7lhweKCtk\n1hvI8mf/Lq98pLzcubYOEg9l1VENAy6VMFi9lGQDWJ4pFs19fzj08RxYzq4N\n5yIB7NpahzgRLhHO7KHImNTXR2d/tlq3VijSnaSEEaQDYa7N7hHZvPVZZxW5\nkI9uJcKGYMUX0ZIl/VNf+yV4ASvtNeZm3rxVOyRykz1GXdOB6J1LFb39Dt5j\naTNlU502ygL02Kjn5x4GLsQ99X9BETryHZOa5ujyjK4TaSwlJKuVr/1E6ZcA\nXs13Emz20idnYBFyGh7B4K18eWy3bq84V9MzMpTFefl2bx7KdR+jJav9QDrT\nyxMO+kmLvl4wWWn4xktxFl/6dAnSQx9WsDMkN5iLPUzS91dBzFp+oIxN9flo\nT4GStJSK4r9/aABwTZc571pxaukVq4b+A/JPkm42YwCF3nSGpod7PpGO/X2W\nESi6LbgRQUdS88ff+sywOaYwQNzQTKoxNCrGAKnbxwzTCI6e3qQwmVVTPbJp\nGamcYK0Bqnd+UOEif3dumZZVzi5Ut8BDtQnCwYLdqPOOjh8l2nP9Zdwo7wAf\nsFMjiXnW3a3tdHLAmyZ9OUI70/LfyC8VqKVOmGPL9Wt2inyBz/KIoVrEinV4\nmxlhqra71nKuASYK4jii+blozOsOqT8XDcH5edHyUT/aYd2uhgjVWDTeFRhy\nsg4B\r\n=G7Uq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDgS5G17s9I4a5cQ6zpiTCDZ+9ZbDQxNmPnJYhdVujl+wIgYnqXLT29Ur9Yu806PueESsthlnZTx+JT6/8iaXGkEB8="}]},"_npmUser":{"name":"xud6","email":"admin@xdq.me"},"maintainers":[{"name":"xud6","email":"admin@xdq.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ember-composability-tools_0.0.15_1629344861197_0.40946011990918674"},"_hasShrinkwrap":false}},"time":{"created":"2021-08-19T03:31:07.809Z","0.0.13":"2021-08-19T03:31:08.002Z","modified":"2022-04-05T07:28:49.395Z","0.0.14":"2021-08-19T03:40:58.640Z","0.0.15":"2021-08-19T03:47:41.356Z"},"maintainers":[{"name":"xud6","email":"admin@xdq.me"}],"description":"Helpers for building a somewhat different kind of components.","homepage":"https://github.com/xud6/ember-composability-tools#readme","keywords":["ember-addon","composability","utilities"],"repository":{"type":"git","url":"git+https://github.com/xud6/ember-composability-tools.git"},"author":{"name":"xud6"},"bugs":{"url":"https://github.com/xud6/ember-composability-tools/issues"},"license":"MIT","readme":"ember-composability-tools 0.0.x\n\n# ember-composability-tools\n\n[![Build Status](https://travis-ci.org/miguelcobain/ember-composability-tools.svg)](https://travis-ci.org/miguelcobain/ember-composability-tools) [![Ember Observer Score](http://emberobserver.com/badges/ember-composability-tools.svg)](http://emberobserver.com/addons/ember-composability-tools) [![Discord](https://img.shields.io/discord/480462759797063690.svg?logo=discord)](https://discord.gg/zT3asNS)\n\nThis addon intends to provide helpers for building a somewhat different kind of components, i.e components which primary goal isn't to render DOM.\n\n* Ember.js v3.16 or above\n* Ember CLI v2.13 or above\n* Node.js v10 or above\n\nTo install this addon, run the usual\n```\nember install ember-composability-tools\n```\n\n## Background and motivation\n\nThis addon was essencially extracted from [ember-leaflet](https://github.com/miguelcobain/ember-leaflet) and then adapted for more generic scenarios. The idea behind ember-leaflet is to compose components the usual way, but to have them to produce leaflet layers and not DOM. To do that, Ember's [component lifecycle hooks](https://guides.emberjs.com/v2.8.0/components/the-component-lifecycle/) are used to create the leaflet layers and not produce any DOM (tagless and templateless components).\n\nThis idea sounded good in theory, but in practice some problems appeared. The following sections will illustrate both those problems and how **ember-composability-tools** helps solving them.\n\n### 1. Lifecycle hooks order\n\nConsider the following template:\n\n```hbs\n{{#leaflet-map lat=51.505 lng=-0.09 zoom=13}}\n\n  {{tile-layer url=\"http://sometiles.com/{z}/{x}/{y}.png\"}}\n\n  {{#maker-layer lat=51.505 lng=-0.09}}\n    {{#popup-layer}}\n      Hello World!\n    {{/popup-layer}}\n  {{/maker-layer}}\n\n{{/leaflet-map}}\n```\n\nWe would like it to be equivalent to the corresponding code using the Leaflet API:\n\n```js\nlet map = L.map(this.element).setView([51.505, -0.09], 13);\nL.tileLayer('http://sometiles.com/{z}/{x}/{y}.png').addTo(map);\nL.marker([51.505, -0.09]).bindPopup('Hello World!').addTo(map);\n```\n\nIn other words, there is an order that needs to be followed. This order is more evident when there are more levels of nesting, but in this case the order is:\n\n1. create map\n2. create tile\n3. create marker\n\nUnfortunately, this isn't the order that any of the lifecycle hooks trigger. E.g, if we had a `console.log('didInsertElement');` in each `didInsertElement` hook, we would see the following order ([demo in ember-twiddle](https://ember-twiddle.com/d1606d4fffecfdeb3257c6effa06cad8?openFiles=templates.application.hbs%2C)):\n\n```\ndidInsertElement <-- tile-layer\ndidInsertElement <-- marker-layer\ndidInsertElement <-- leaflet-map\n```\n\nThe render hooks start being called on children, which is not compatible with our 3rd party API logic.\nAlso, we need to use `didInsertElement` at least on `leaflet-map` because we need to make sure an element is available to create a map (`L.map(this.element)`). This is a very common pattern, not only with leaflet.\n\nLikewise, the destroy lifecycle hooks are not called in the desired order.\n\n**ember-composability-tools** fixes this problem providing components new render and destroy hooks that trigger in our desired order. Those hooks are called `didInsertParent` and `willDestroyParent`. You just need to include `ChildMixin` on child components and `ParentMixin` on parent components to have access to them. Example:\n\n```js\nimport Ember from 'ember';\nimport { ParentMixin } from 'ember-composability-tools';\nconst { Component } = Ember;\n\nexport default Component.extend(ParentMixin, {\n  didInsertParent() {\n    this._super(...arguments);\n    // The topmost parent hook call.\n    // Here we have a `this.element` available and\n    // we are certain that none of the children's\n    // `didInsertParent` hooks were called\n  },\n  willDestroyParent() {\n    this._super(...arguments);\n    // the reverse is applied here.\n    // We are certain that this call will take place\n    // when all of the children's `willDestroyParent`\n    // were called.\n  }\n});\n```\n\nThe same hooks are available when using `ChildMixin`.\n\nNote that a component can be a child and a parent at the same time. e.g `marker-layer` is a child to `leaflet-map` but a parent to `popup-layer`. In that case just include both mixins. They are compatible.\n\n### 2. Access to parent and children\n\nWhile composing components like we say in our previous ember-leaflet example, we often need to access parent/child components. E.g, when we write:\n\n```hbs\n{{#leaflet-map lat=51.505 lng=-0.09 zoom=13}}\n  {{tile-layer url=\"http://sometiles.com/{z}/{x}/{y}.png\"}}\n{{/leaflet-map}}\n```\n\nwe want the child tile-layer to be added to the **parent** map instance. In other cases one might need to access children directly from the parent.\n\nWith **ember-composability-tools** we can essentially do:\n\n```js\n// tile-layer example implementation\nL.tileLayer(this.get('url')).addTo(this.get('parentComponent')._mapInstance);\n```\n\n`parentComponent` is available on any component that includes the `ChildMixin` and is used inside the block of a component that includes the `ParentMixin`.\n\nLikewise, the `childComponents` property is available on a component that includes the `ParentMixin`:\n\n```js\n// invoke draw on all child components\nthis.get('childComponents').invoke('draw');\n```\n\n### 3. Render blocks as DOM, but not to the document\n\nThe third problem **ember-composability-tools** aims to solve is the problem of getting the  contents of a block as a DOM you can pass in to a 3rd party library.\nIf you take a closer look, in our previous example we had:\n\n```hbs\n{{#maker-layer lat=51.505 lng=-0.09}}\n  {{#popup-layer}}\n    Hello World!\n  {{/popup-layer}}\n{{/maker-layer}}\n```\n\nBut how will that `Hello World!` ends up in a leaflet popup? Using the leaflet API, we quickly that problem:\n\n```js\nL.marker([this.get('lat'), this.get('lng')])\n  .bindPopup(?) // how do we get the contents of the block of the current component?\n  .addTo(this.get('parentComponent')._mapInstance);\n```\n\nAt first sight one might ask \"Why not just `this.$()` or `this.element`?\". The problem in doing this is that the contents would still be rendered to the DOM in the document, like normally. Remember that at this stage we're in a DOM zone that \"isn't ours\". It belongs to the leaflet map and we're not sure how leaflet treats the DOM here, so it might not be safe to change the DOM here. We should only \"render\" leaflet layers by now.\n\n**ember-composability-tools** solves this problem by rendering the component's block to an element created by the component itself (using `document.createElement()`).\n\nTo use this functionality you just need to include the `RenderBlockMixin`. By default, the `RenderBlockMixin` doesn't render anything to the `destinationElement`. This way you don't render anything you don't want to. You control when to render by setting `shouldRender` to `true` or `false`.\n\nExample:\n\n```js\nimport Ember from 'ember';\nimport { RenderBlockMixin } from 'ember-composability-tools';\nconst { Component } = Ember;\n\nexport default Component.extend(RenderBlockMixin, {\n  // use `this.get('destinationElement')` in the component context\n  // in this case we decided to always render the block\n  // so we set shouldRender to true at init time.\n  shouldRender: true\n});\n```\n\nContributing\n------------------------------------------------------------------------------\n\n### Installation\n\n* `git clone <repository-url>`\n* `cd ember-composability-tools`\n* `npm install`\n\n### Linting\n\n* `npm run lint:hbs`\n* `npm run lint:js`\n* `npm run lint:js -- --fix`\n\n### Running tests\n\n* `ember test` – Runs the test suite on the current Ember version\n* `ember test --server` – Runs the test suite in \"watch mode\"\n* `ember try:each` – Runs the test suite against multiple Ember versions\n\n### Running the dummy application\n\n* `ember serve`\n* Visit the dummy application at [http://localhost:4200](http://localhost:4200).\n\nFor more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/).\n\nLicense\n------------------------------------------------------------------------------\n\nThis project is licensed under the [MIT License](LICENSE.md).\n","readmeFilename":"README.md"}