user3662516
user3662516

Reputation: 79

Mithril - Rerender dynamic content

I am trying to re render my DOM elemnets after my deferred object returns with data. I debug this on the console and it appears that my elements are getting created, however it never shows up to the page. If I add static content it works as intended.

        m('div', {class: 'table-responsive'}, [
            m('table', {class: 'table'}, [
                m("thead", [
                    m('tr', [
                        m('th', '#'),
                        m('th', 'Groups'),
                    ])
                ]),
                m('tbody', findGroupsDeferred.promise.then(function(data){ // findGroupsDeferred returns when the promise is complete with my data.
                    data.group.map(function(group) {
                        return m("tr", [
                            m("td", [
                                m("input[type=checkbox] checked", {
                                    value: group,
                                    onclick: function (event) {
                                        if (event.target.checked) {
                                            ctrl.addGroup(ctrl.groups(event.target.value))
                                        } else {
                                            ctrl.removeGroup(ctrl.groups(event.target.value))
                                        }
                                    }
                                })
                            ]),
                            m("td", group),
                        ])
                    });
                }))
            ])
        ]),

Upvotes: 0

Views: 839

Answers (2)

Stephan Hoyer
Stephan Hoyer

Reputation: 4928

Roamer-1888 Is quite right. This can't be done in the view. You have a few options to achieve this:

First on is to wait for the result in the controller:

controller: function() {
  scope = {
    groups: []
  }
  findGroupsDeferred.promise.then(function(data) {
    scope.groups = data.group;
  }
  return scope;
},
view: function(scope) {
  return scope.groups.map(function(group) {
    return group.name // or what ever you want to do here
  }
}

Another option is to create a component for this which pretty much results in the same code accept the it's encapsulated. Third option is to use m.prop together with mithrils defered for this.

Upvotes: 2

Roamer-1888
Roamer-1888

Reputation: 19288

I don't know mithril but would guess that a promise can't be used in quite that way.

From first principles of promises, it would make more sense to wrap the entire m() expression with promise.then(...). In other words, build the entire table after findGroupsDeferred.promise resolves, rather than trying to target an inner portion of the table.

findGroupsDeferred.promise.then(function(data) { // findGroupsDeferred returns when the promise is complete with my data.
    m('div', {class: 'table-responsive'}, [
        m('table', {class: 'table'}, [
            m("thead", [
                m('tr', [
                    m('th', '#'),
                    m('th', 'Groups'),
                ])
            ]),
            m('tbody', data.group.map(function(group) {
                return m("tr", [
                    m("td", [
                        m("input[type=checkbox] checked", {
                            value: group,
                            onclick: function (event) {
                                if (event.target.checked) {
                                    ctrl.addGroup(ctrl.groups(event.target.value));
                                } else {
                                    ctrl.removeGroup(ctrl.groups(event.target.value));
                                }
                            }
                        })
                    ]),
                    m("td", group),
                ]);
            }))
        ])
    ]),
});

Alternatively mithril has a mechanism for rendering before web service requests finish, which may be relevant here.

Upvotes: 1

Related Questions