mithril.js
A Javascript Framework for Building Brilliant Applications (development repo)
Mithril
mithril talks plenty about binding and eventing if they are simple variable changes, but what about binding say the +
key to functionality? I tried m.withAttr('keyCode')
binding to the controller method that I wanted to handle it, but nothing.
Sample Code
Source: (StackOverflow)
I am using Mithril as our MVC framework & I want to leverage of rich JQuery/Jquery UI functionalities. I would like to understand the 'Do's and Don't's' when combining jQuery with Mithril
What I understand is, I can use Mithril config to access the real DOM element & bind to various jQuery functions safely.
Using jQuery UI functions with Mithril
But what about using jQuery selectors on classes or ids to locate the real DOM element, like
attaching a jQuery date picker
beforeShow: function(input, inst) {
$('#ui-datepicker-div').addClass("mydatepicker");
},
or hiding a div
$("#mydiv").hide();
What is the danger of inprogress m.render causing $('blah') === undefined.
Would really like to understand the how these 2 components could/should interact with each other.
Source: (StackOverflow)
I am using Firefox 32 and Chrome 37 with Mithril.js
and have now been repeatedly tripped up by typos in variable names just silently causing the JS to stop executing at the point of the reference. It's particularly frustrating for me coming from C and Java since I am used to the compiler catching such trivial mistakes before I even attempt to run the code.
I have narrowed down the problem to be occurring only in functions running as part of the AJAX promise chain, like this:
function getListData(ctl) {
ctl.data([]);
ctl.loading(true);
return m.request({ method: "GET", url: apiBase, background: true }).then(done,fail);
function done(rspdta) {
xctl.loading(false);
ctl.data(rspdta.Customer);
m.redraw();
};
function fail(rspdta) {
ctl.loading(false);
ajaxError(ctl);
m.redraw();
throw rspdta; // continue error condition
};
}
Notice the deliberate xctl.loading(false)
in the done
function -- the script just appears to stop there, but a ReferenceError
is thrown. However, nothing is logged.
I am working on how to prove have proved that it's being caught and ignored by Mithril.js
now, in this code:
function thennable (ref, cb, ec, cn) {
if ((typeof val == 'object' || typeof val == 'function') && typeof ref == 'function') {
try {
// cnt protects against abuse calls from spec checker
var cnt = 0
ref.call(val, function (v) {
if (cnt++) return
val = v
cb()
}, function (v) {
if (cnt++) return
val = v
ec()
})
} catch (e) {
/**/console.log("[**] Caught in thennable: %o",e);
val = e
ec()
}
} else {
cn()
}
};
Hopefully someone from that community will be able to say whether I've done something wrong, am misusing the promise chain (??) or if it's a bug in Mithril.js
0.1.21.
Source: (StackOverflow)
I want to know how to modify Polymer 1.0 tags after creation via jQuery or virtual DOM.
I am trying Polymer 1.0 with Mithril.js. Polymer 0.5.5 has Shadow DOM and its tag literal and internal structure (on Chrome's inspector) are almost same. But 1.0 uses shady DOM and it works as HTML template.
Source:
<paper-element>hello world</paper-element>
Polymer 0.5.5 result on inspector:
<paper-button role="button" tabindex="0">hello world</paper-button>
Polymer 1.0 result on inspector:
<paper-button role="button" tabindex="0" aria-disabled="false" class="x-scope paper-button-0">
<paper-ripple class="style-scope paper-button">
<div id="background" class="style-scope paper-ripple"></div>
<div id="waves" class="style-scope paper-ripple"></div>
</paper-ripple>
<paper-material animated="" class="content style-scope paper-button x-scope paper-material-0" elevation="0">
hello world
</paper-material>
</paper-button>
For example, performing jQuery command like this:
$("paper-element").text("new label");
It works with 0.5.5 (it shows correct label), but breaks 1.0 (internal tags have gone ant becomes just label). This new behavior is not good for manipulating Polymer's custom tags via other DOM manipulation library (at first, I hit this issue when I am playing Mithril.js). And I can't find any API to reinitialize internal tags.
Is there any good solution to modify Polymer 1.0 tag after creation to support virtual DOM or jQuery?
Update (6/3/2015)
I found solution from Polymer document. Polymer 1.0 can work on Mithril virtual DOM after adding the following snippet:
<script>
window.Polymer = window.Polymer || {};
window.Polymer.dom = 'shadow';
</script>
Polymer starts using Shadow DOM instead of default Shady DOM by this setting. It is as same as Polymer 0.5.5 and JavaScript DOM API friendly. Thank you guys!
Source: (StackOverflow)
I am trying to unit test a Mithril model using m.request
in a DOM-less environment.
I have this test working as an integration test in a browser environment using the browser's XMLHttpRequest, but would like the option to run this in isolation.
I am considering mocking the response of XMLHttpRequest in order to get a properly initialized m.request
, but I'm not sure where to start. I have a naive implementation of XMLHttpRequest driven out from the test and have looked into the source of m.request
, but as a relative JS-newbie it's hard to follow.
Does it make more sense to stub out m.request
entirely with to just test the transformation, since I trust that Mithril works (and is technically a dependency of the unit under test)? This scares me a bit as m.request
has the chaining behavior which might be tricky to stub.
I would gladly accept an answer that generally describes the steps I would need to take to make some progress on this, and/or some advice on what makes sense to test.
require('chai').should();
require('mithril');
m.deps({ XMLHttpRequest: function() {
this.open = function() {
}
this.setRequestHeader = function() {
}
this.send = function() {
}
}});
var Curriculum = require('../../../app/modules/practice/practice.curriculum');
describe('Curriculum', function() {
it('can retrieve a list of modules', function(done) {
Curriculum.modules().then(function(modules) {
modules.should.deep.equal([
{ name: 'Module 1' },
{ name: 'Module 2' },
{ name: 'Module 3' }
]);
done();
});
});
});
Currently, running this test with mocha
times out unhelpfully with no output or errors.
The source of the unit under test, if helpful:
module.exports = {
modules: function() {
// URL obscured to protect the innocent.
return m.request({
method: 'GET',
url: 'http://working.url'
}).then(function(objects) {
var transformed = objects.map(function(object) {
return { name: object.name };
});
return transformed;
});
}
};
Source: (StackOverflow)
I just started reading about Mithril. Fascinating..
Just one thing that puzzles me after first read.
How can I route one component inside another (top-level component)? I mean, how do I emulate angulars ng-view or embers outlet?
I understand that I can get m.route to attach components to any dom node.
But how can I render say top level component App, which generates m("#view") among other things, and then all other routable components go inside App's #view div? Is this possible? Otherwise I have to repeatedly include header and footer with every route transition to a subcomponent, right? Am I missing something?
Thank you.
Source: (StackOverflow)
I recently started learning mithril.js and I'm wondering how can I make very basic Model -> View one way data binding app.
TestModel = function(data){
this.name = m.prop(data.name)
}
testModel = new TestModel({name: "John"})
code above declare a model and it works perfectly as getter/setter.
but how can I set an event listener for the model event like Backbone's listenTo('model',"change",callbackFunc)
?
all sample codes I saw are setting events for actual user actions like click
,keyup
or onchange
.but never listen to actual model value's state directly.
am I missing something or am I understanding how to use mithril.js wrongly?
thanks in advance.
Source: (StackOverflow)
I use Dalek to test my sample to-do application written with help of Mithril framework.
Everything goes fine until .type()
comes in.
If I .type()
something in input
that have bi-directional binding m.prop
with m.withAttr
and then assert
values of that field i get strage behaviour. Instead "test title"
I get "tsttle"
. It seems that test are running too quickly for Mithril to capture changes and render them back to DOM.
If assertions for input equality is removed — all works just fine.
Is there any workaround, can I slow down type process?
P.S. I use Chrome browser as test runner.
Source: (StackOverflow)
I have draggable li
elements nested in a ul
in turn nested in a div
, as seen below:
<div class='group'>
<div class='header'>
// some stuff here
</div>
<ul>
<li draggable='true'>
Stuff I want to drag and drop to another div.group
</li>
</ul>
</div>
There are multiple of these div
elements and I am trying to implement a drag & drop functionality to move the li
elements of one div
group to another.
I have hooked up the ondragenter
, ondragleave
callbacks here:
// controller using mithril.js
ctrl.onDragLeave = function () {
return function (event) {
var target;
// Using isDropzone to recursively search for the appropriate div.group
// parent element, as event.target is always the children inside it
if ((target = isDropzone(event.target)) != null) {
target.style.background = "";
}
}
};
ctrl.onDragEnter = function () {
return function (event) {
var target;
if ((target = isDropzone(event.target)) != null) {
target.style.background = "purple";
}
};
};
function isDropzone(elem){
if(elem == null){
return null;
}
return elem.className == 'group' ? elem: isDropzone(elem.parentNode)
}
The problem comes when the event.target
of the callbacks are always the nested child elements inside the div
, such as li
, and thus the callbacks are constantly fired. In this case I'm changing the color of the div.group
with my callbacks, resulting in the div.group
blinking undesirably.
Is there a way to delegate events and only allow the div
grand parent of li
to handle the events? Or any other way to work around this?
EDIT: Would still love to find out if there's a way to do this, but right now I'm using the workaround I found here.
Source: (StackOverflow)
I'm a bit stuck looking for the right way to do the following. I have a parent component with two child components (see simplified code below). I would like to know the proper way for ChildA, when its button is pressed, to 'invoke' ChildB . They should communicate through the parent, but should they communicate through their controllers? In that case the parent has to pass its controller to the controllers of the children.
Parent = {
view: function () {
m.component(ChildA);
m.component(ChildbB;
}
}
ChildA = {
view: function () {
m('button')
}
}
ChildB = {
view: function () {
}
}
Source: (StackOverflow)
Currently I am creating a simple app using Mithril
and CoffeeScript
.
The code is as follows:
m = require 'mithril'
login = {}
login.controller = ->
@email = m.prop ''
@password = m.prop ''
@onSubmit = ->
return
return
login.view = (ctrl) ->
m 'center.login', [
m 'aside.logo', m "img[src='/img/logo.svg']"
m 'article.heading', m 'h3','Enter your email and password'
m "input.email[placeholder='email'][type='email']",
onchange: m.withAttr('value', ctrl.email)
value: ctrl.email()
m "input.password[placeholder='password'][type='password']"
onchange: m.withAttr('value', ctrl.password)
value: ctrl.password()
m "submit.button button-primary[rel='nofollow' href='/#/signup']",
onclick: ctrl.onSubmit()
value: 'Submit'
]
m.mount document.getElementById('content'), login
module.exports = view: login.view
When I run the app, it gives me the following error:
Uncaught TypeError: ctrl.email is not a function
I am thinking the possible reason of the error is because the mount
function is not configured with the module properly.
Why is the m.prop() not working here?
Source: (StackOverflow)
I have a mock json file that I want to read into an object. My code looks like this:
m = require('mithril');
/* .. snip .. */
var foo = m.prop([]);
m.request({
method: 'GET',
url: './foo.json',
unwrapSuccess: function (a, b) {
console.log("success");
},
unwrapError: function (a, b) {
console.log("error");
}
}).then(function (a) {
// fill in foo
console.log("object filled");
});
The code always hits only the unwrapError
hook.
What is really confusing me are these two things:
- The request is made successfully - I can see it in Chrome's dev tools. There is no indication of access error whatsoever;
- The first argument received by the error hook is the very JSON I expect; the second argument is the corresponding XMLHttpRequest object, without any indication of error.
So contrary to the documentation, the response object does not contain an "error" property telling me what happened.
What am I doing wrong?
Source: (StackOverflow)
I need to receive http status errors with m.request
so I use extract
as per documentation. But it messes up my data return for some reason.
According to docs, if I use extract
to get status then extract
return is passed as a parameter to the error callback and data is passed to the success callback. Here is the snippet from docs.
var nonJsonErrors = function(xhr) {
return xhr.status > 200 ? JSON.stringify(xhr.responseText) : xhr.responseText
}
m.request({method: "GET", url: "/foo/bar.x", extract: nonJsonErrors})
.then(function(data) {}, function(error) {console.log(error)})
Now, I get status in both success and error callbacks which is wrong.
I need to get status on error and data on success. How do I do this? What am I doing wrong? Here is my code:
var Application = {
run() {
m.request({
method: "GET",
url: "http://localhost:3000/api/session/ping",
extract(xhr) {return xhr.status;}
}).then((data) => {
console.log("Session is Up");
console.log(data);
var init = {
uname: data.uname
};
router(init);
}, (error) => {
console.log(`Cought: ${error}`);
m.mount(document.body, Login);
});
}
};
Both error and data here give me status codes. I need to get incoming data on success to set up my authentication.
Thanks.
Source: (StackOverflow)
When using pure bootstrap there is a small horizontal space between buttons.
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<button class="btn btn-primary">Save</button>
<button class="btn btn-default">Cancel</button>
</div>
</div>
</div>
This space disappears if elements are created with mithril.js:
var my = {};
my.view = function() {
return m('.container-fluid',
m('.row',
m('.col-xs-12', [
m('button.btn.btn-default', 'Save'),
m('button.btn.btn-default', 'Cancel')
])
)
);
};
m.mount(document.body, my);
What causes bootstrap to add small space between buttons? How to reproduce that in mithril.js?
Source: (StackOverflow)
Trying to get the hang of Mithril, can't really understand one thing. Can I render components on events?
Let's assume I have one parent component:
var MyApp = {
view: function() {
return m("div", [
m.component(MyApp.header, {}),
m("div", {id: "menu-container"})
])
}
};
m.mount(document.body, megogo.main);
It renders the header component (and a placeholder for the menu (do I even need it?)):
MyApp.header = {
view: function() {
return m("div", {
id: 'app-header'
}, [
m('a', {
href: '#',
id: 'menu-button',
onclick: function(){
// this part is just for reference
m.component(MyApp.menu, {})
}
}, 'Menu')
])
}
}
When the user clicks on the menu link I want to load the menu items from my API and only then render the menu.
MyApp.menu = {
controller: function() {
var categories = m.request({method: "GET", url: "https://api.site.com/?params"});
return {categories: categories};
},
view: function(ctrl) {
return m("div", ctrl.categories().data.items.map(function(item) {
return m("a", {
href: "#",
class: 'link-button',
onkeydown: MyApp.menu.keydown
}, item.title)
}));
},
keydown: function(e){
e.preventDefault();
var code = e.keyCode || e.which;
switch(code){
// ...
}
}
};
This part will obviously not work
onclick: function(){
// this part is just for reference
m.component(MyApp.menu, {})
}
So, the question is what is the correct way render components on event?
Source: (StackOverflow)