Premium support for our pure JavaScript UI components


Post by Luffy »

I have written an async tooltip which was worked well on Bryntum Scheduler 2.1.0
Bryntum Scheduler version 2.1.0
Bryntum Scheduler version 2.1.0
Bryntum Scheduler 2.1.0.gif (1.39 MiB) Viewed 1640 times
then I had to upgrade the version into Bryntum Scheduler 2.2.5 and now the tooltiip doesnt work.
Bryntum Scheduler version 2.2.5
Bryntum Scheduler version 2.2.5
Bryntum Scheduler 2.2.5.gif (1.38 MiB) Viewed 1640 times
    eventTooltip: {
      template: () => false,
      listeners: {
        beforeShow: ({ source: tip }) => {
          makeEventTootip(tip);
        }
      },
      align: 'l-r',
      // hide tooltip when the dom scrolls
      floating: true,
      scrollAction: 'hide',
      style: { fontSize: '0.9rem' }
    },
async function makeEventTootip(tip) {
  indexKey = tip.eventRecord.data.id;
  tableName = tip.eventRecord.data.eventType;
  eventContextType = tip.eventRecord.data.eventType.toString()[0];
  controlData = await db.getTableDataByKey('controllData', 1);
  const url = controlData.companyDetails.drillbackURL;
  tooltipData = controlData.tooltips.find(eventTooltipInfo => {
    return eventTooltipInfo.context === eventContextType;
  });
  contextFields = tooltipData.fields;
  dataRecord = await db.getTableDataByKey(tableName, indexKey);

  const contextFieldsList = () => {
    const tooltipValuesArray = contextFields.map(field => {
      let tooltipValues;
      if (field.action) {
        const hrefValue = url.concat(field.action, dataRecord[field.field]);
        console.log('hrefValue : ', hrefValue);
        tooltipValues = `<dt>${
          field.title
        } : <a href='${hrefValue}' target="_blank">${
          dataRecord[field.field]
        }</a></dt>`;
      } else {
        tooltipValues = `<dt>${field.title} : ${dataRecord[field.field]}</dt>`;
      }
      console.log('tooltipValues : ', tooltipValues);

      return tooltipValues;
    });
    return tooltipValuesArray.join(' ');
  };
  tip.html = `${contextFieldsList()}`;
}
Any idea what has happened ?
All i did was upgrading the bryntum version.

Post by Maxim Gorkovsky »

Hello.
What happens here is this:
1. Default tip is show with 'Loading' text, because of the template: () => false
2. Async function resolves and changes tip html
3. Tip html gets updated and tip element is resized (2.1.0 used to stop here)
4. Tip gets realigned to the target (which is valid cause, since content might start violating aligning rules after resize)
5. Overridden aligning method on the tooltip class updates tip html

I opened a ticket to fix this: https://app.assembla.com/spaces/bryntum/tickets/9383-impossible-to-update-tip-html-in-runtime/details

As a workaround without much overriding I would suggest to also return html on step 5 also, e.g. from template method. Smth like:
makeEventTooltip(tip) {
	...
	if (tip.isVisible) {
	  tip.html = tip.myCachedHtml = ...
	}
}

eventTooltip: {
      template: function() { return this.tooltip._myCachedHtml || false },
      listeners: {
        beforeShow: ({ source: tip }) => {
          makeEventTootip(tip);
        },
        hide : ({ source : tip }) => tip._myCachedHtml = false
      },
      align: 'l-r',
      // hide tooltip when the dom scrolls
      floating: true,
      scrollAction: 'hide',
      style: { fontSize: '0.9rem' }
    }
    

Post by Luffy »

Hi,
I tried your suggestion but no luck.
    eventTooltip: {
      template: function() {
        return this.tooltip._myCachedHtml || false;
      },
      listeners: {
        beforeShow: ({ source: tip }) => {
          makeEventTootip(tip);
        },
        hide: ({ source: tip }) => (tip._myCachedHtml = false)
      },
      align: 'l-r',
      // hide tooltip when the dom scrolls
      floating: true,
      scrollAction: 'hide',
      style: { fontSize: '0.9rem' }
    },
async function makeEventTootip(tip) {
  if (!tip.isVisible) {
    return;
  }
  indexKey = tip.eventRecord.data.id;
  tableName = tip.eventRecord.data.eventType;
  eventContextType = tip.eventRecord.data.eventType.toString()[0];
  controlData = await db.getTableDataByKey('controllData', 1);
  const url = controlData.companyDetails.drillbackURL;
  tooltipData = controlData.tooltips.find(eventTooltipInfo => {
    return eventTooltipInfo.context === eventContextType;
  });
  contextFields = tooltipData.fields;
  dataRecord = await db.getTableDataByKey(tableName, indexKey);

  const contextFieldsList = () => {
    const tooltipValuesArray = contextFields.map(field => {
      let tooltipValues;
      if (field.action) {
        const hrefValue = url.concat(field.action, dataRecord[field.field]);
        console.log('hrefValue : ', hrefValue);
        tooltipValues = `<dt>${
          field.title
        } : <a href='${hrefValue}' target="_blank">${
          dataRecord[field.field]
        }</a></dt>`;
      } else {
        tooltipValues = `<dt>${field.title} : ${dataRecord[field.field]}</dt>`;
      }
      console.log('tooltipValues : ', tooltipValues);

      return tooltipValues;
    });
    return tooltipValuesArray.join(' ');
  };
  tip.html = `${contextFieldsList()}`;
}

Post by Maxim Gorkovsky »

You are missing part where you actually cache the html string

Post by Luffy »

forgot that part to send. Still no luck.

my code looks like this.
async function makeEventTootip(tip) {
  if (!tip.isVisible) {
    return;
  }
  indexKey = tip.eventRecord.data.id;
  tableName = tip.eventRecord.data.eventType;
  eventContextType = tip.eventRecord.data.eventType.toString()[0];
  controlData = await db.getTableDataByKey('controllData', 1);
  const url = controlData.companyDetails.drillbackURL;
  tooltipData = controlData.tooltips.find(eventTooltipInfo => {
    return eventTooltipInfo.context === eventContextType;
  });
  contextFields = tooltipData.fields;
  dataRecord = await db.getTableDataByKey(tableName, indexKey);

  const contextFieldsList = () => {
    const tooltipValuesArray = contextFields.map(field => {
      let tooltipValues;
      if (field.action) {
        const hrefValue = url.concat(field.action, dataRecord[field.field]);
        console.log('hrefValue : ', hrefValue);
        tooltipValues = `<dt>${
          field.title
        } : <a href='${hrefValue}' target="_blank">${
          dataRecord[field.field]
        }</a></dt>`;
      } else {
        tooltipValues = `<dt>${field.title} : ${dataRecord[field.field]}</dt>`;
      }
      console.log('tooltipValues : ', tooltipValues);

      return tooltipValues;
    });
    return tooltipValuesArray.join(' ');
  };
  tip.html = tip.myCachedHtml = `${contextFieldsList()}`;
}
    eventTooltip: {
      template: function() {
        return this.tooltip._myCachedHtml || false;
      },
      listeners: {
        beforeShow: ({ source: tip }) => {
          makeEventTootip(tip);
        },
        hide: ({ source: tip }) => (tip._myCachedHtml = false)
      },
      align: 'l-r',
      // hide tooltip when the dom scrolls
      floating: true,
      scrollAction: 'hide',
      style: { fontSize: '0.9rem' }
    },
    
values assign. but tooltip disappears.
tooltip.png
tooltip.png (84.56 KiB) Viewed 1627 times

Post by Maxim Gorkovsky »

You store value to tip.myCachedHtml and read it from tip._myCachedHtml

Post by Luffy »

Thanks dude. Sorry about that.
I have done the changes but still doesn't work as expected.
    eventTooltip: {
      template: function() {
        return this.tooltip.html || false;
      },
      listeners: {
        beforeShow: ({ source: tip }) => {
          makeEventTootip(tip);
        },
        hide: ({ source: tip }) => (tip._myCachedHtml = false)
      },
      align: 'l-r',
      floating: true, // hide tooltip when the dom scrolls
      scrollAction: 'hide',
      style: { fontSize: '0.9rem' }
    },
async function makeEventTootip(tip) {
  indexKey = tip.eventRecord.data.id;
  tableName = tip.eventRecord.data.eventType;
  eventContextType = tip.eventRecord.data.eventType.toString()[0];
  controlData = await db.getTableDataByKey('controllData', 1);
  const url = controlData.companyDetails.drillbackURL;
  tooltipData = controlData.tooltips.find(eventTooltipInfo => {
    return eventTooltipInfo.context === eventContextType;
  });
  contextFields = tooltipData.fields;
  dataRecord = await db.getTableDataByKey(tableName, indexKey);

  const contextFieldsList = () => {
    const tooltipValuesArray = contextFields.map(field => {
      let tooltipValues;
      if (field.action) {
        const hrefValue = url.concat(field.action, dataRecord[field.field]);
        tooltipValues = `<dt>${
          field.title
        } : <a href='${hrefValue}' target="_blank">${
          dataRecord[field.field]
        }</a></dt>`;
      } else {
        tooltipValues = `<dt>${field.title} : ${dataRecord[field.field]}</dt>`;
      }
      console.log('tooltipValues : ', tooltipValues);

      return tooltipValues;
    });
    return tooltipValuesArray.join(' ');
  };
  if (tip.isVisible) {
    tip.html = tip._myCachedHtml = `${contextFieldsList()}`;
  }
}
tooltip.gif
tooltip.gif (5.44 MiB) Viewed 1623 times
As you can see in the attached giff, at the first time when hover on to the event it gives an error.

Then it shows it's relevant values.

then hover to another event, and it shows previous event's values (I think it is taking from the cache).

Need to mouse hover twice to get the relevant tooltips data for the particular event.

Post by Maxim Gorkovsky »

Debug the error and see what is going on? Probably it throws because eventRecord is missing on the tip instance. Related event record gets cached on the tip during render. So after `beforeshow` event and before `template` method call. So if you move beforeshow logic to `template` method returning false from it, exception should go away.
eventTooltip: {
      template: function({ eventRecord }) {
        this.tooltip.eventRecord = eventRecord;
        makeEventTootip(tip);
        return this.tooltip.html || false;
      },
      listeners: {
        hide: ({ source: tip }) => (tip._myCachedHtml = false)
      }
    },

Post by Luffy »

No luck. Error has gone. But the tool tip doesn't appear at all.

Can you please make this work as it worked in previous bryntum versions.
Cannot do alternate changes for well worked features whenever upgrading the bryntum.

A ticket is already opened.

https://app.assembla.com/spaces/bryntum/support/tickets/9383-impossible-to-update-tip-html-in-runtime.

Post Reply