TypeError on x-editables "destroy" function


#1

Hello,
I’m trying to get a x-editable / select2 component with reactive options following this example: http://stackoverflow.com/a/36323435. Use case is to show a select field for adding users to a team. The select options consist of suggested users, who are not already team mates. Every time a new user is added to the team, suggested users are recalculated and delivered to current data context by parent template helper.
This is my onRendered function:

Template.addMember.onRendered(function() {
  var tmplInst = this;
  this.autorun(function() {
    data = Blaze.getData();
    tmplInst.$('.add-member').editable("destroy").editable({
      type: 'select2',
      title: "add member",
      placeholder: "Choose a member",
      emptytext: "Add a member",
      validate: function(value) {
        if($.trim(value) == '') {
          return "Please choose a member!";
        }
      },
      source: function() {
        return data.suggestedUsers;
      },
      success: function(response, newValue) {
        var draftId = $(this).data("pk");
        ProjectDrafts.update(draftId, {$push: { team: {userId: newValue} } });
        $(this).editable("value", null);
      },
    });
  });
});

Sometimes it works all as expected, but sometimes (only when whole page is reloaded) the editable is not shown up at all and I get this error in Chrome console:

TypeError: Cannot read property 'data' of undefined
    at Constructor.destroy (bootstrap-editable.js:3893)
    at Editable.destroy (bootstrap-editable.js:1939)
    at HTMLAnchorElement.<anonymous> (bootstrap-editable.js:2143)
    at Function.each (jquery.js:384)
    at jQuery.fn.init.each (jquery.js:136)
    at jQuery.fn.init.$.fn.editable (bootstrap-editable.js:2125)
    at Blaze.View.<anonymous> (new_project.js:190)
    at view.js:199
    at Function.Template._withTemplateInstanceFunc (template.js:465)
    at view.js:197

Any suggestions? Thanks in advance!


#2

2 thinks to look out for here:

  • Is all of your data available and loaded? Stick a quick piece of code on the return from Blaze.getData() and take a look around, e.g.
data = Blaze.getData();
if(!data) {
debugger;
}
  • I have been using x-editable. And I have been using the blaze templating to initialize the select. When I do this I need to wait for all the DOM commands to flush. So what I do is:
Template.templateName.onCreated(() => {
  let template = this;
  ...
  // subscribe to my data sources e.g.
  template.subSource = template.subscribe('source');
  ...
  template.autorun(() => {
    ...
    // when subscription is ready e.g.
    if(template.subSource.ready()) {
      ...
      // wait for Dom to flush
      // Necessary because my helpers depend upon updated data and they get
      // busy once the data sources are ready
      Tracker.afterFlush( () => {
        ...
        // OK, now I can make calls on the x-editable component
        $fn.editable.defaults ...
        $('.editable').editable(...

I was having a few troubles with my code being unpredictable until I understood that I needed to wait for all DOM manipulations to complete. And I reach that point after a Tracker.afterFlush(). Now things are much more predictable.