Embedded LWC chart not refreshing on sales forecast record updates

When users update a sales forecast record, the embedded Chart.js LWC showing pipeline trends doesn’t refresh automatically. Users must manually refresh the browser to see updated data.

The component uses @wire decorator with getRecord to fetch forecast data:

@wire(getRecord, { recordId: '$recordId', fields: FIELDS })
forecastRecord;

After a user updates forecast amount or probability fields, the chart still shows old values. I tried calling getRecordNotifyChange() after updates but it’s not triggering the wire adapter to re-fetch. The component is embedded in a Sales Forecast record page flexipage. Real-time chart updates are critical for our weekly forecast calls with 30+ sales managers reviewing live data. How do I force the wire adapter to refresh when the underlying record changes?

Your chart refresh issue requires addressing all three focus areas: Lightning Data Service wire adapters for record data, getRecordNotifyChange usage for LDS cache invalidation, and real-time chart updates for the Chart.js visualization. Here’s the comprehensive solution:

Lightning Data Service Wire Adapters: You’re using two separate wire adapters: getRecord for the forecast record and a custom Apex wire for opportunity data. These have different refresh mechanisms. The getRecord wire adapter automatically refreshes when LDS detects record changes made through Lightning Data Service (updateRecord, createRecord). However, your custom @wire(getOpportunities) doesn’t participate in LDS cache, so it never auto-refreshes.

Modify your component to store the wired Apex result properly:

wiredOpportunitiesResult;
@wire(getOpportunities, { forecastId: '$recordId' })
wiredOpportunities(result) {
  this.wiredOpportunitiesResult = result;
  if (result.data) {
    this.processChartData(result.data);
  }
}

Storing the result object (not just data) enables refreshApex to work.

getRecordNotifyChange Usage: getRecordNotifyChange only invalidates LDS-managed records, not custom Apex query results. Use it after updating the forecast record itself to refresh the getRecord wire, but for the opportunity data, import and use refreshApex:

import { refreshApex } from '@salesforce/apex';
import { getRecordNotifyChange } from 'lightning/uiRecordApi';

async handleForecastUpdate() {
  // After update logic
  getRecordNotifyChange([{recordId: this.recordId}]);
  await refreshApex(this.wiredOpportunitiesResult);
}

Call refreshApex with the stored result object, not the data property. This re-executes your getOpportunities Apex method and fetches fresh data.

Real-Time Chart Updates: Chart.js requires explicit update() calls when data changes. Create a reactive pattern that updates the chart whenever wire data changes:

processChartData(data) {
  this.chartData = this.transformToChartFormat(data);
  if (this.chartInstance) {
    this.chartInstance.data = this.chartData;
    this.chartInstance.update('none');
  }
}

The ‘none’ animation parameter makes updates instant, crucial for live forecast calls. Initialize this.chartInstance in renderedCallback when the canvas element is ready.

For your 30+ managers scenario where multiple users view the same forecast simultaneously, implement Change Data Capture to broadcast updates:

  1. Enable CDC on Opportunity object (Setup > Change Data Capture > Select Opportunity)
  2. Subscribe to CDC events in your LWC using empApi
  3. When a CDC event arrives, call refreshApex to update the chart

This ensures when one manager updates opportunities, all other managers’ charts refresh automatically without manual browser refresh. The combination of refreshApex for local updates and CDC for broadcast updates provides complete real-time synchronization across all forecast call participants.

Deploy these changes and your chart will refresh immediately when forecast or opportunity data changes, whether updated by the current user or colleagues in the same forecast review session.


This draft is based on general Salesforce knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

Are you calling getRecordNotifyChange with the correct record ID array? It needs to be an array even for a single record. Also, if your chart data comes from related records or aggregate queries, getRecordNotifyChange won’t help because it only invalidates the specific record cache, not query results. You might need to use refreshApex instead if you’re doing imperative Apex calls for the chart data.

Good point - I am calling it with an array: getRecordNotifyChange([{recordId: this.recordId}]). The chart actually pulls data from multiple related Opportunity records, not just the forecast record itself. I’m using a separate @wire(getOpportunities) to fetch related opps. Should I be using refreshApex for that instead? The getOpportunities is a custom Apex method that aggregates opportunity amounts by stage.

Yes, exactly. Lightning Data Service wire adapters like getRecord only cache standard record data. Your custom Apex method results aren’t part of LDS cache, so getRecordNotifyChange has no effect on them. Import refreshApex from @salesforce/apex and call it with your wired Apex result variable. Store the wired result in a property and call refreshApex(this.wiredOpportunitiesResult) when you need to refresh. This forces the wire adapter to re-execute your Apex method and get fresh data.

Also make sure you’re updating your Chart.js instance in the wired property’s reactive getter. If you’re only initializing the chart in renderedCallback, it won’t update when the wire adapter refreshes. Use a getter that watches for changes to the wired data and calls chart.update() method. Something like: get chartData() { return this.transformData(this.wiredOpportunitiesResult.data); } and watch that in a separate method that updates the chart.

“Tested this on API v59.0 — combining getRecordNotifyChange after Apex DML with manual Chart.js dataset.update() call finally kept our forecast chart in sync.”

Consider using platform events or change data capture if you need real-time updates across multiple users’ screens simultaneously. If one sales manager updates a forecast, other managers viewing the same forecast should see the update too. RefreshApex only works for the user who made the change. For collaborative forecasting, you’d need CDC or PE to push updates to all subscribed components.

The 30+ managers in forecast calls scenario definitely needs broadcast updates, not just local refresh.