Ember.js + JQuery-UI Tooltip - Tooltip does not reflect the model / controller changes

爷,独闯天下 提交于 2019-12-08 03:30:47

问题


Context

I have a small Ember app, which, amongst other things, displays a number of connected users and, when hovering an element of the page, their names as a list.

All in all, it works quite well. The applications pulls data from a REST endpoint every two minutes, as the backend didn't allow for pushing data.

The contents of the tooltip are computed in the Controller, with a function that basically concatenate strings in various ways according to the context. Then it's bound to a data attribute of the <img> the tooltip is created on. When the View is ready and didInsertElement is fired, the tooltip is generated (if needs be) based on this data-bindattr value.

Question

When new data is pulled from the backend, everything is updated accordingly, except the tooltip content. (When browsing the page's DOM, the data-bindattr value is updated too.)

What could cause the tooltip to not refresh? Is it a case of JQuery-UI not calculating it again?

Some code

Refreshing code in the app's controller:

Monitor.ApplicationController = Ember.ArrayController.extend({
  itemController: 'process',
  sortProperties: ['name'],
  sortAscending: true,
  intervalId: undefined,
  startRefreshing: function() {
    var self = this;
    if (self.get('intervalId')) {
      return;
    }
    self.set( 'intervalId', setInterval(function() {
      self.store.find('process');
    }, 120000 ));
  }
});

View: Process.hbs

<div {{bind-attr class=":inline inactive:inactive"}}>
    <img {{bind-attr src=icon}} {{bind-attr data-caption=contentText}} class="caption" />
    <div class="counter">{{nbUsers}}</div>
</div>

View: ProcessView

Monitor.ProcessView = Ember.View.extend({
  // (...) Various stuff.
  didInsertElement: function() {
    this.updateTooltip();
  },
  updateTooltip: function() {  
    console.log('Inside updateTooltip!');
    if (!this.$()) {return;}  
    if (this.get('controller').get('inactive')) {
        this.$().tooltip({items: '.caption', disabled: true});
        return;
    }
    this.$().tooltip({
        items: '.caption',
        tooltipClass: 'tooltip',
        content: function() {
            return $(this).data('caption');
        },
        position: {
            my: 'left+15px center',
            at: 'right center',
            collision: 'flip'
        },
        show: false,
        hide: false
    });
  }.observes('controller.inactive', 'controller.contentText')
});

Controller: ProcessController

Monitor.ProcessController = Ember.ObjectController.extend({
  contentText: function() {
    var tooltipContent = '';
    this.get('containers').forEach(function(container) {
    // Do a lot of things to tooltipContent involving: 
    // container.get('name')
    // container.get('text')
    // container.get('size')
    // container.get('nbUsers')
    // The data-bindattr value refreshes correctly so I cut this out for readability.
    return tooltipContent;
  }.property('name', 'containers.@each')
});

Edit 1:

Replaced 'containers.@each' by 'contentText' in the observer and added logging.


回答1:


Here's what I think is happening:

Your tooltip library isn't observing the data-caption attribute. Meaning, when you update the attribute, you have to explicitly tell the library to update the tooltip as well. So although your attribute is updating just fine, the tooltip library isn't actually watching for those updates.

This can be remedied by calling updateTooltip, which you do, in didInsertElement. However, didInsertElement only fires once, when the element is first inserted. It's not called when the content changes.

Those two things combined are, I think, causing your problem. I think that all you need to do is have updateTooltip also observe the controller.contextText property. Then it should be called when the text updates.




回答2:


So it turns out my codes declares and initialize a tooltip, but once it's done, you can't change the content the same way. Plus it adds unneeded computing anyway.

Thanks to @GJK's answer and that question, I found out what was happening. Turns out you need to set the content of the tooltip to refresh it, not recreate it.

Here is the working code for Ember integration:

Monitor.ProcessView = Ember.View.extend({
  // Other stuff
  didInsertElement: function() {
    this.initTooltip();
  },
  initTooltip: function() {  
    if (!this.$()) {return;}  
    if (this.get('controller').get('inactive')) {
        this.$().tooltip({items: '.caption', disabled: true});
        return;
    }
    this.$().tooltip({
        items: '.caption',
        tooltipClass: 'tooltip',
        content: function() {
            return $(this).data('caption');
        },
        position: {
            my: 'left+15px center',
            at: 'right center',
            collision: 'flip'
        },
        show: false,
        hide: false
    });
  },
  updateTooltip: function() {
    if (!this.$()) {return;}  
    if (this.get('controller').get('inactive')) {
        this.$().tooltip({items: '.caption', disabled: true});
        return;
    }
    content = this.get('controller').get('contentText');
    this.$().tooltip("option", "content", content);
  }.observes('controller.contentText')
});

As an added bonus, you can avoid using the data attribute as a buffer now, although I'm not sure why.



来源:https://stackoverflow.com/questions/24952117/ember-js-jquery-ui-tooltip-tooltip-does-not-reflect-the-model-controller-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!