Reputation: 773
I have 2 components - addProjectForm
and listProjects
. They are both nested components inside the root module. Whenever I add a project using the form, I want it to appear in the list straight away.
To achieve this, I had to pass down the controller instance to each component like this:
var RootComponent = {};
rootComponent.controller = function() {
this.example = 'test variable';
}
rootComponent.view = function(ctrl) {
return [
m.component(addProjectForm, ctrl),
m.component(listProjects, ctrl)
];
}
and then the listProjects
component for example, looks like this:
var listProjects = {
controller: function(root) {
this.root = root;
},
view: function(ctrl) {
console.log(ctrl.root.example);
}
};
So this way I keep calling methods on the top level, but I don't quite like passing down the controller instance like this. Is there any other way I should be doing it?
Upvotes: 1
Views: 1407
Reputation: 4928
The problem you have is the difference between passing by reference or by value. In JS all primitive types are passed by value. Thats why you can't pass the string directly since it's cloned during pass. You have multiple options here:
You can use m.prop and just pass the variable down to the components, m.props stores the value in function that is always passed by reference.
var RootComponent = {};
rootComponent.controller = function() {
this.example = m.prop('test variable');
}
rootComponent.view = function(ctrl) {
return [
m.component(addProjectForm, ctrl.example),
m.component(listProjects, ctrl.example)
];
}
If the variable is an array, it will be passed by reference anyways.
Second option is to keep the list in the root context and add a callback to the second component.
var RootComponent = {};
rootComponent.controller = function() {
var projects = this.projects = [];
this.addProject = function(project) {
projects.push(project);
}
}
rootComponent.view = function(ctrl) {
return [
m.component(addProjectForm, {
onsubmit: ctrl.addProject
}),
m.component(listProjects, ctrl.projects)
];
}
Upvotes: 0
Reputation: 1105
I think this is what you're looking for:
Mithril.js: Should two child components talk to each other through their parent's controller?
A newer way of solving this common problem is to use a Flux like architecture developed by Facebook:
https://facebook.github.io/flux/
Writing your own dispatcher is semi-trivial. Here's an example that someone else built alongside Mithril:
https://gist.github.com/MattMcFarland/25fb4f0241530d2f421a
The downside with this approach is it would be somewhat anti-Flux to use m.withAttr, as views aren't supposed to write directly to models in the dispatcher paradigm.
Upvotes: 0