EzDevInfo.com

mithril.js

A Javascript Framework for Building Brilliant Applications (development repo) Mithril

How would I bind keypresses for an app?

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)

How does Mithril and jQuery interact with each other?

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)

Advertisements

ReferenceError from within Mithril promise chain is being silently ignored

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)

Polymer 1.0 and external DOM manipulation library

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)

How can I unit test a model using m.request in Mithril?

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)

MithrilJS: Routing a component inside top level component

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)

How to detect model parameter change event in mithril.js?

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)

DalekJS and Mithril: Test are too fast

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)

Delegating Draggable Events to Parent Elements

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)

Mithril.js: Should two child components talk to each other through their parent's controller?

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)

m.prop() not working as expected

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)

Successful requests get unwrapped in error hook

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)

MithrilJS: How to get XHR.status on error and data on success with m.request()

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)

Horizontal space between bootstrap buttons using mithril.js

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)

Mithril: render component on event/dynamically

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)