0

A contrived example of bi-directional data binding

var user = {
    model: function(name) {
        this.name = m.prop(name);
    },
    controller: function() {
        return {user: new user.model("John Doe")};
    },
    view: function(controller) {
        m.render("body", [
            m("input", {onchange: m.withAttr("value", controller.user.name), value: controller.user.name()})
        ]);
    }
};

https://lhorie.github.io/mithril/mithril.withAttr.html


I tried the above code does not work nothing.

It was the first to try to append the following.

m.mount(document.body, user);

Uncaught SyntaxError: Unexpected token n


Then I tried to append the following.

var users = m.prop([]);
var error = m.prop("");
m.request({method: "GET", url: "/users/index.php"})
        .then(users, error); 

▼/users/index.php

<?php
echo '[{name: "John"}, {name: "Mary"}]';

Uncaught SyntaxError: Unexpected token n


How do I operate the m.withAttr tutorials code?

re6
  • 37
  • 1
  • 5

2 Answers2

1

Try returning m('body', [...]) from your controller.

view: function (ctrl) {
    return m("body", [
        ...
    ]);
}

render should not be used inside of Mithril components (render is only used to mount Mithril components on existing DOM nodes).

Matthew King
  • 1,342
  • 7
  • 13
0

The example is difficult to operate because it's contrived, it's not meant to be working out-of-the-box. Here's a slightly modified, working version:

http://jsfiddle.net/ciscoheat/8dwenn02/2/

var user = {
    model: function(name) {
        this.name = m.prop(name);
    },
    controller: function() {
        return {user: new user.model("John Doe")};
    },
    view: function(controller) {
        return [
            m("input", {
                oninput: m.withAttr("value", controller.user.name),
                value: controller.user.name()
            }),
            m("h1", controller.user.name())
        ];
    }
};

m.mount(document.body, user);

Changes made:

  1. m.mount injects html inside the element specified as first parameter, so rendering a body element in view will make a body inside a body.
  2. Changed the input field event to oninput for instant feedback, and added a h1 to display the model, so you can see it changing when the input field changes.

Using m.request

Another example how to make an ajax request that displays the retrieved data, as per your modifications:

http://jsfiddle.net/ciscoheat/3senfh9c/

var userList = {
    controller: function() {
        var users = m.prop([]); 
        var error = m.prop("");

        m.request({
            method: "GET", 
            url: "http://jsonplaceholder.typicode.com/users",
        }).then(users, error);

        return { users: users, error: error };
    },
    view: function(controller) {
        return [
            controller.users().map(function(u) {
                return m("div", u.name)
            }),
            controller.error() ? m(".error", {style: "color:red"}, "Error: " +  controller.error()) : null
        ];
    }
};

m.mount(document.body, userList);

The Unexpected token n error can happen if the requested url doesn't return valid JSON, so you need to fix the JSON data in /users/index.php to make it work with your own code. There are no quotes around the name field.

ciscoheat
  • 3,719
  • 1
  • 35
  • 52