--
You received this message because you are subscribed to the Google Groups "mithril" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mithriljs+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Mithril stands out because it's minimalistic (and fast). If component communication is (hopefully) incorporated into core, I hope it is just as minimal. Something like routing -- basic but functional. For those who need more functionality there's moria -- and hopefully more options in the future.
--
You received this message because you are subscribed to the Google Groups "mithril" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mithriljs+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
<html>
<head>
...
</head>
<body>
<script id="page-script">MyComponent.create(document.getElementById('page-script').parentNode,MyView);</script>
</body>
</html>
The main differences between this proof of concept and Mithril.Elements are:- instead of registering via Mithril.Elements' `m.element` function, you register a component by adding it to the `m.tags` map- the controller extends the virtual dom element, and no extra parameters are passed to the view
The main things it brings to the table are:- it leverages the virtual dom cache tree, so it has the same positional identity semantics as everything else in Mithril (i.e. no need for hard coding component ids, ever)- it supports controller.onunload
There are a few loose ends that may or may not be issues:1) Mithril.Elements allow returning arrays from component templates. This version doesn't. i.e. `m("foo")` can expand to `[m("a"), m("b")]` in Mithril.Elements. In my version, it can only expand to something with a single root element. The primary reason is that it's really hard to support controller.onunload. The only argument I can come up with for allowing arrays as return values is consistency. But neither Angular or React support replacing the component's tag with multiple elements, and you can't really support onunload properly in that case given that DOM elements can be moved and removed, disintegrating the "component". So maybe not allowing arrays as template return values is a reasonable limitation.
2) Mithril.Elements supports escaped versions of custom tags (i.e. you can make table do magic, and $table be the fallback regular table tag. Personally, I don't like the idea of overriding regular tags because it can lead to WTF moments for no good reason. Instead, it's trivial to register a `$table` element that does the magic and leave `table` alone. And I think it's a lot more obvious where the magic comes from, when reading the code.
3) This proof of concept always uses "replace" semantics (i.e. `m("MyComponent")` never spits out a <MyComponent> tag to the DOM, instead it replaces it with the component's markup). Riot has non-replace semantics all the time. Angular has a `replace` option in its directive API, Having always-replace semantics means you can't use the component's tag name to namespace it for CSS styling. This is trivial to get around (just add a class to the root element of the component), but technically it's still a weakness. I don't like Riot's approach because then you can't add attributes to the component tag itself, and the tag always pollutes the DOM tree. Angular's feature is, imho, the kind of thing that seems good on paper, but contribute to its death-by-a-thousand-paper-cuts complexity issue in reality. So I think always-replace semantics is the way to go.
Compositional order might be an issue though. A tag designer might need to establish a parent context before building the child view. And this leads to the idea of tightly coupled tag assemblies (tabset / tab etc) which might be harder to achieve without control over order.
To allow the instance to choose the type of list, why not:```m.tags["List"] = {controller: function() {},view: function(ctrl) {return m(ctrl.attrs.type, [ctrl.attrs.items.length ? ctrl.attrs.items.map(ctrl.children[0]) : ctrl.children[1]()])}}
m.customTag = function customTag(elementName, definition) { var module = {}; if (definition.toString() === '[object Object]') { module.controller = definition.controller || function(node) {}; module.view = definition.view;
} else if (typeof definition === 'function') { module.controller = function(node) {}; module.view = definition;
} else if (typeof definition === 'string') { module.controller = function(node) {}; module.view = function(ctrl) { return m(definition, ctrl.attrs, ctrl.children); };
} else { throw new Error('invalid tag definition given');
} m.tags[elementName] = module;};
// calls go like this, empty controllers will be added
// 1. simple tag
m.customTag('appbar', 'header.appbar'); //=> m('appbar', attrs, children) => <header class="appbar"></header>
//2. nested view
m.customTag('labeledCheckbox', function(node) {
return m('label', [
node.attrs.label,
m('input[type=checkbox])
]);
});
//=> m('labeledCheckbox', { label: 'check me' }) => <label>check me<input type="checkbox" /></label>
// 3. fullblown module
m.customTag('myFullblownTag', {
controller: function(){ ... },
view: function(ctrl) { ... }
});
@Phil it's doable, but it's a task left to the component developer.
StandaloneComponent: {
controller: function() {
// ...
},
view: function(ctl) {
//...
},
}
App: {
controller: function() {
m.tags["widget"]=StandaloneComponent;
},
view: function(ctl) {
return m("div.container", [
...
m("widget", ...),
...
]);
}
App: {
controller: function() {
this.widget=new StandaloneComponent.controller;
},
view: function(ctl) {
return m("div.container", [
...
return StandaloneComponent.view(ctl.widget),
...
]);
}
m.tags["List"] = {controller: function() {},view: function(ctrl) {return m(ctrl.attrs.type, [ctrl.attrs.items.length ? ctrl.attrs.items.map(ctrl.children[0]) : ctrl.children[1]()])}}
A 'List' component should be able to establish style for both its 'ul' and 'li' constituents.
@LawrenceI didn't intend that a component reach into other child components. [...]
Re your additional point:We are working inside the view, so it seems appropriate that button dropdown vs navbar dropdown should be dealt with on a case by case basis.
@Philo,
The design of CSS & HTML actually makes it hard to specify default styling in the view (which would naturally be `style` attributes) without precluding external styling via a CSS file, unless the CSS file specifies "!important" all over the place. This is a deficiency in CSS not Mithril, but it's a deficiency we're stuck with.
@Lawrence yeah, I've been thinking a lot about how best to approach this. Mithril elements is great, but I agree that there needs to be something in core to address the issues around positional identity of components
--
You received this message because you are subscribed to the Google Groups "mithril" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mithriljs+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
m.tags[ myCoolComponent: {module: 'pointerToMyCoolComponent.controller', id: '8437502347' } ]
m.tags[ 'myAwesomeComponent' ] with internal representation as m.tags[ 'myAwesomeComponent_id750918345' ]
small correction: in the example for item 3, it should be `new FooWithArgs.controller()`, not `new FooWithArgs()`. I've pasted the corrected snippet in the Github discussion thread ( https://github.com/lhorie/mithril.js/issues/413#issuecomment-72304725 )
--
You received this message because you are subscribed to the Google Groups "mithril" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mithriljs+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.