Reputation: 683
I have a mithril component with an controller which is already bounded to an context, if I use m.component(), mithril disregards the bounded controller and supplies the view with an default empty controller
UserWidget = function(){
this.allUsers = User.load();
this['header'] = {
'controller' : function(users){
this.users = users;
}.bind(this, this.allUsers),
'view' : function(ctrl) {
console.log('ctrl', ctrl)
if (ctrl.users()) {
return m('.user', ctrl.users()[0].name());
}
}
}
}
//initialize
m.module(document.body, m(new UserWidget().header));
However if I pass view/controller via m.module everything works as expected
m.module(document.body, new UserWidget().header);
https://jsfiddle.net/chifer/mwddffy4/2/
Is it a caveat that component controllers should be unbounded and passed params via the m.component call? or is this a bug?
Upvotes: 2
Views: 348
Reputation: 16456
Is it a caveat that component controllers should be unbounded and passed params via the m.component call?
Yes. Controllers are invoked as constructors with the new
keyword, which means this
(and arguments passed in) cannot be bound to it.
Your code can be simplified by avoiding this
and binding internally:
UserWidget = function(){
var users = User.load();
return {
'view' : function() {
if (users())
return m('.user', users()[0].name());
}
}
}
//initialize
m.module(document.body, m(UserWidget()));
But in practice, this code is replicating the functionality that's already built in to controllers — to quote from the Mithril API documentation for components:
The optional controller function creates an object that may be used in the following recommended ways:
[...]
Basically, your original application code involves a constructor that makes a request and stores a reference to the returned promise, and this is exactly what controllers are for. So you can avoid writing any intermediary functions or constructors of your own and bake all that functionality into the component structure itself:
UserWidget = {
'controller' : function(){
this.users = User.load();
},
'view' : function(ctrl) {
if (ctrl.users())
return m('.user', ctrl.users()[0].name());
}
}
//initialize
m.module(document.body, UserWidget);
Upvotes: 1