当前位置: 动力学知识库 > 问答 > 编程问答 >

javascript - Mithril - how to populate drop down list of view from API

问题描述:

I'm trying to populate a drop down box rendered by Mithril's view from methods being called outside of its module (not sure if this terminology is correct, but outside of the property which contains the view, model and controller).

This Chrome extension adds a new field to an existing page and depending on what the user select, the drop down box should refresh to items pertaining to the selected item. I can get up to the stage of getting the new list of items, but i cannot get the drop down list to redraw with the new objects.

The following shows the module which gets inserted inside an existing page:

var ItemsList = {

model: function () {

this.list = function (id) {

var d = m.deferred()

// Calls Chrome extension bg page for retrieval of items.

chromeExt.getItems(pId, function (items) {

// Set default values initially when the controller is called.

if (items.length === 0) {

items = [

{name: 'None', value: 'none'}

]

}

d.resolve(items || [])

})

return d.promise

}

},

controller: function () {

this.model = new ItemsList.model()

this.index = m.prop(0)

this.onchange = function (e) {

console.info('ctrl:onchange', e.target)

}

// Initialise the drop down list array list.

this.dropDownItemsList = m.prop([]);

// This sets the default value of the drop down list to nothing by calling the function in the model,

// until the user selects an item which should populate the drop down list with some values.

this.getItems = function(pId) {

this.model.list(pId).then(function (data) {

this.dropDownItemsList(data)

m.redraw()

}.bind(this))

}

this.getItems(0);

},

view: function (ctrl) {

var SELECT_ID = 'record_select'

return vm.Type() ? m('div', [

m('.form__item', [

m('.label', [

m('label', {

htmlFor: SELECT_ID

}, 'ID')

]),

m('.field', [

m('select#' + SELECT_ID, {

onchange: ctrl.onchange.bind(ctrl)

},

ctrl.dropDownItemsList().map(function (it, i) {

return m('option', {

value: it.value,

checked: ctrl.model.index === i

}, it.name)

})

),

])

]),

]) : null

}

}

And it is mounted using

m.mount("element name here", ItemsList);

The code which checks to see if the item has changed is using a mutation observer, and whenever it detects changes to a certain field, it will call a method to get the new values. I can see that the return value has my new items.

I have tried various different methods on trying to update the drop down list, first by trying to set the "this.list" with the new items list i've got, or trying to create a returnable method on the controller which i can call when the mutation observer fires.

After getting the new items, how can i make the drop down list show the new items which has been retrieved?

I have read guides which shows functions in the controller or model being run - but only if they've been defined to use them already in the view (i.e. have an onclick method on the view which calls the method) but so far i cannot figure out how to update or call methods from outside of the module.

Is there a way to achieve the above or a different method i should approach this?

网友答案:

After some more research into how Mithril works, seems like that it's not possible to call any functions defined within the component.

Due to this, i have moved the model outside of the component (so now it only has the controller and the view defined) and bound the view to use the model outside of the component.

Now calling a function which updates the model (which is now accessible from elsewhere in the code) and redrawing shows the correct values that i need.

网友答案:

If I understand correctly, you need to have two variables to store your lists, one to store the old list and one to store the updated list so you can always map the updated one and go to your old one if you need.

Here is a simple implementation of a drop down list with some methods to update and search. You can update the list on the fly using the methods.

  • mithDropDown
  • jsFiddle

    var MythDropDown = function(list) {
  if (Array.isArray(list))
    this.list = list;
  else
    list = [];
  if (!(this instanceof MythDropDown))
    return new MythDropDown(list);

  var self = this;
  this.selected = {
    name: list[0],
    index: 0
  };
  this.list = list;
};

MythDropDown.prototype.view = function(ctrl) {
  var self = this;
  return m('select', {
      config: function(selectElement, isinit) {
        if (isinit)
          return;
        self.selectElement = selectElement;
        self.update(self.list);
      },
      onchange: function(e) {
        self.selected.name = e.target.value;
        self.selected.index = e.target.selectedIndex;

      }
    },

    this.list.map(function(name, i) {
      return m('option', name);
    }));
};

MythDropDown.prototype.getSelected = function() {
  return (this.selected);
};

MythDropDown.prototype.update = function(newList) {

  this.list = newList;
  this.selectElement.selectedIndex = 0;
  this.selected.name = newList[0];
  this.selected.index = 0;
};

MythDropDown.prototype.sort = function() {
  this.list.sort();
  this.update(this.list);
};

MythDropDown.prototype.delete = function() {
  this.list.splice(this.selected.index, 1);
  this.update(this.list);

};

var list = ['test option 1', 'test option 2'];
var myList = new MythDropDown(list);

var main = {
  view: function() {
    return m('.content',
      m('button', {
          onclick: function() {
            var L1 = ['Banana', 'Apple', 'Orange', 'Kiwi'];
            myList.update(L1);
          }
        },
        'Fruits'),
      m('button', {
          onclick: function() {
            var L1 = ['Yellow', 'Black', 'Orange', 'Brown', 'Red'];
            myList.update(L1);
          }

        },
        'Colors'),
      m('button', {
          onclick: function() {

            myList.sort();
          }

        },
        'Sort'),
      m('button', {
          onclick: function() {

            myList.delete();
          }

        },
        'Remove Selected'),

      m('', m.component(myList),
        m('', 'Selected Item: ' + myList.selected.name, 'Selected Index: ' + myList.selected.index)

      )

    );
  }
};

m.mount(document.body, main);
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/0.2.3/mithril.min.js"></script>
分享给朋友:
您可能感兴趣的文章:
随机阅读: