diff --git a/docs/change-log.md b/docs/change-log.md index f8d11ff11..4151b9d3b 100644 --- a/docs/change-log.md +++ b/docs/change-log.md @@ -66,7 +66,7 @@ - render/events: `Object.prototype` properties can no longer interfere with event listener calls. - render/events: Event handlers, when set to literally `undefined` (or any non-function), are now correctly removed. - render/hooks: fixed an ommission that caused `oninit` to be called unnecessarily in some cases [#1992](https://github.com/MithrilJS/mithril.js/issues/1992) -- docs: tweaks: ([#2104](https://github.com/MithrilJS/mithril.js/pull/2104) [@mikeyb](https://github.com/mikeyb), [#2205](https://github.com/MithrilJS/mithril.js/pull/2205), [@cavemansspa](https://github.com/cavemansspa), [#2265](https://github.com/MithrilJS/mithril.js/pull/2265), [@isiahmeadows](https://github.com/isiahmeadows)) +- docs: tweaks: ([#2104](https://github.com/MithrilJS/mithril.js/pull/2104) [@mikeyb](https://github.com/mikeyb), [#2205](https://github.com/MithrilJS/mithril.js/pull/2205), [@cavemansspa](https://github.com/cavemansspa), [#2250](https://github.com/MithrilJS/mithril.js/pull/2250) [@isiahmeadows](https://github.com/isiahmeadows), [#2265](https://github.com/MithrilJS/mithril.js/pull/2265), [@isiahmeadows](https://github.com/isiahmeadows)) - render/core: avoid touching `Object.prototype.__proto__` setter with `key: "__proto__"` in certain situations ([#2251](https://github.com/MithrilJS/mithril.js/pull/2251)) - render/core: Vnodes stored in the dom node supplied to `m.render()` are now normalized [#2266](https://github.com/MithrilJS/mithril.js/pull/2266) - render/core: CSS vars can now be specified in `{style}` attributes [#2192](https://github.com/MithrilJS/mithril.js/pull/2192) diff --git a/docs/components.md b/docs/components.md index d7a3fb99b..1c1cadf77 100644 --- a/docs/components.md +++ b/docs/components.md @@ -126,7 +126,7 @@ function ComponentWithState(initialVnode) { // Component state variable, unique to each instance var count = 0 - // POJO component instance: any object with a + // POJO component instance: any object with a // view function which returns a vnode return { oninit: function(vnode){ @@ -431,6 +431,70 @@ This way, the `Auth` module is now the source of truth for auth-related state, a As a bonus, notice that we no longer need to use `.bind` to keep a reference to the state for the component's event handlers. +#### Don't forward `vnode.attrs` itself to other vnodes + +Sometimes, you might want to keep an interface flexible and your implementation simpler by forwarding attributes to a particular child component or element, in this case [Bootstrap's modal](https://getbootstrap.com/docs/4.1/components/modal/). It might be tempting to forward a vnode's attributes like this: + +```javascript +// AVOID +var Modal = { + // ... + view: function(vnode) { + return m(".modal[tabindex=-1][role=dialog]", vnode.attrs, [ + // forwarding `vnode.attrs` here ^ + // ... + ]) + } +} +``` + +If you do it like above, you could run into issues when using it: + +```js +var MyModal = { + view: function() { + return m(Modal, { + // This toggles it twice, so it doesn't show + onupdate: function(vnode) { + if (toggle) $(vnode.dom).modal("toggle") + } + }, [ + // ... + ]) + } +} +``` + +Instead, you should forward *single* attributes into vnodes: + +```js +// PREFER +var Modal = { + // ... + view: function(vnode) { + return m(".modal[tabindex=-1][role=dialog]", vnode.attrs.attrs, [ + // forwarding `attrs:` here ^ + // ... + ]) + } +} + +// Example +var MyModal = { + view: function() { + return m(Modal, { + attrs: { + // This toggles it once + onupdate: function(vnode) { + if (toggle) $(vnode.dom).modal("toggle") + } + }, + // ... + }) + } +} +``` + #### Don't manipulate `children` If a component is opinionated in how it applies attributes or children, you should switch to using custom attributes.