Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4f7a513

Browse files
Merge pull request #7475 from plotly/react-to-config-changes
fix: React to config changes
2 parents a7eac49 + 6133268 commit 4f7a513

File tree

3 files changed

+123
-109
lines changed

3 files changed

+123
-109
lines changed

‎draftlogs/7475_fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Update plot with all config changes during call to `Plotly.react` [#7475](https://github.com/plotly/plotly.js/pull/7475)

‎src/plot_api/plot_api.js

Lines changed: 120 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -2615,129 +2615,140 @@ function react(gd, data, layout, config) {
26152615
configChanged = diffConfig(oldConfig, gd._context);
26162616
}
26172617

2618-
gd.data = data || [];
2619-
helpers.cleanData(gd.data);
2620-
gd.layout = layout || {};
2621-
helpers.cleanLayout(gd.layout);
2622-
2623-
applyUIRevisions(gd.data, gd.layout, oldFullData, oldFullLayout);
2624-
2625-
// "true" skips updating calcdata and remapping arrays from calcTransforms,
2626-
// which supplyDefaults usually does at the end, but we may need to NOT do
2627-
// if the diff (which we haven't determined yet) says we'll recalc
2628-
Plots.supplyDefaults(gd, {skipUpdateCalc: true});
2629-
2630-
var newFullData = gd._fullData;
2631-
var newFullLayout = gd._fullLayout;
2632-
var immutable = newFullLayout.datarevision === undefined;
2633-
var transition = newFullLayout.transition;
2634-
2635-
var relayoutFlags = diffLayout(gd, oldFullLayout, newFullLayout, immutable, transition);
2636-
var newDataRevision = relayoutFlags.newDataRevision;
2637-
var restyleFlags = diffData(gd, oldFullData, newFullData, immutable, transition, newDataRevision);
2638-
2639-
// TODO: how to translate this part of relayout to Plotly.react?
2640-
// // Setting width or height to null must reset the graph's width / height
2641-
// // back to its initial value as computed during the first pass in Plots.plotAutoSize.
2642-
// //
2643-
// // To do so, we must manually set them back here using the _initialAutoSize cache.
2644-
// if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
2645-
// fullLayout[ai] = gd._initialAutoSize[ai];
2646-
// }
2647-
2648-
if(updateAutosize(gd)) relayoutFlags.layoutReplot = true;
2649-
2650-
// clear calcdata and empty categories if required
2651-
if(restyleFlags.calc || relayoutFlags.calc) {
2652-
gd.calcdata = undefined;
2653-
var allNames = Object.getOwnPropertyNames(newFullLayout);
2654-
for(var q = 0; q < allNames.length; q++) {
2655-
var name = allNames[q];
2656-
var start = name.substring(0, 5);
2657-
if(start === 'xaxis' || start === 'yaxis') {
2658-
var emptyCategories = newFullLayout[name]._emptyCategories;
2659-
if(emptyCategories) emptyCategories();
2618+
if(configChanged) {
2619+
// Save event listeners as newPlot will remove them
2620+
const eventListeners = gd._ev.eventNames().map(name => [name, gd._ev.listeners(name)]);
2621+
plotDone = exports.newPlot(gd, data, layout, config)
2622+
.then(() => {
2623+
for (const [name, callbacks] of eventListeners) {
2624+
callbacks.forEach((cb) => gd.on(name, cb));
2625+
}
2626+
2627+
// Call react in case transition should have occurred along with config change
2628+
return exports.react(gd, data, layout, config)
2629+
});
2630+
} else {
2631+
gd.data = data || [];
2632+
helpers.cleanData(gd.data);
2633+
gd.layout = layout || {};
2634+
helpers.cleanLayout(gd.layout);
2635+
2636+
applyUIRevisions(gd.data, gd.layout, oldFullData, oldFullLayout);
2637+
2638+
// "true" skips updating calcdata and remapping arrays from calcTransforms,
2639+
// which supplyDefaults usually does at the end, but we may need to NOT do
2640+
// if the diff (which we haven't determined yet) says we'll recalc
2641+
Plots.supplyDefaults(gd, {skipUpdateCalc: true});
2642+
2643+
var newFullData = gd._fullData;
2644+
var newFullLayout = gd._fullLayout;
2645+
var immutable = newFullLayout.datarevision === undefined;
2646+
var transition = newFullLayout.transition;
2647+
2648+
var relayoutFlags = diffLayout(gd, oldFullLayout, newFullLayout, immutable, transition);
2649+
var newDataRevision = relayoutFlags.newDataRevision;
2650+
var restyleFlags = diffData(gd, oldFullData, newFullData, immutable, transition, newDataRevision);
2651+
2652+
// TODO: how to translate this part of relayout to Plotly.react?
2653+
// // Setting width or height to null must reset the graph's width / height
2654+
// // back to its initial value as computed during the first pass in Plots.plotAutoSize.
2655+
// //
2656+
// // To do so, we must manually set them back here using the _initialAutoSize cache.
2657+
// if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
2658+
// fullLayout[ai] = gd._initialAutoSize[ai];
2659+
// }
2660+
2661+
if(updateAutosize(gd)) relayoutFlags.layoutReplot = true;
2662+
2663+
// clear calcdata and empty categories if required
2664+
if(restyleFlags.calc || relayoutFlags.calc) {
2665+
gd.calcdata = undefined;
2666+
var allNames = Object.getOwnPropertyNames(newFullLayout);
2667+
for(var q = 0; q < allNames.length; q++) {
2668+
var name = allNames[q];
2669+
var start = name.substring(0, 5);
2670+
if(start === 'xaxis' || start === 'yaxis') {
2671+
var emptyCategories = newFullLayout[name]._emptyCategories;
2672+
if(emptyCategories) emptyCategories();
2673+
}
26602674
}
2675+
// otherwise do the calcdata updates and calcTransform array remaps that we skipped earlier
2676+
} else {
2677+
Plots.supplyDefaultsUpdateCalc(gd.calcdata, newFullData);
26612678
}
2662-
// otherwise do the calcdata updates and calcTransform array remaps that we skipped earlier
2663-
} else {
2664-
Plots.supplyDefaultsUpdateCalc(gd.calcdata, newFullData);
2665-
}
26662679

2667-
// Note: what restyle/relayout use impliedEdits and clearAxisTypes for
2668-
// must be handled by the user when using Plotly.react.
2680+
// Note: what restyle/relayout use impliedEdits and clearAxisTypes for
2681+
// must be handled by the user when using Plotly.react.
26692682

2670-
// fill in redraw sequence
2671-
var seq = [];
2683+
// fill in redraw sequence
2684+
var seq = [];
26722685

2673-
if(frames) {
2674-
gd._transitionData = {};
2675-
Plots.createTransitionData(gd);
2676-
seq.push(addFrames);
2677-
}
2686+
if(frames) {
2687+
gd._transitionData = {};
2688+
Plots.createTransitionData(gd);
2689+
seq.push(addFrames);
2690+
}
26782691

2679-
// Transition pathway,
2680-
// only used when 'transition' is set by user and
2681-
// when at least one animatable attribute has changed,
2682-
// N.B. config changed aren't animatable
2683-
if(newFullLayout.transition&&!configChanged && (restyleFlags.anim || relayoutFlags.anim)) {
2684-
if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout);
2692+
// Transition pathway,
2693+
// only used when 'transition' is set by user and
2694+
// when at least one animatable attribute has changed,
2695+
// N.B. config changed aren't animatable
2696+
if(newFullLayout.transition && (restyleFlags.anim || relayoutFlags.anim)) {
2697+
if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout);
26852698

2686-
Plots.doCalcdata(gd);
2687-
subroutines.doAutoRangeAndConstraints(gd);
2699+
Plots.doCalcdata(gd);
2700+
subroutines.doAutoRangeAndConstraints(gd);
26882701

2689-
seq.push(function() {
2690-
return Plots.transitionFromReact(gd, restyleFlags, relayoutFlags, oldFullLayout);
2691-
});
2692-
} else if(restyleFlags.fullReplot || relayoutFlags.layoutReplot || configChanged) {
2693-
gd._fullLayout._skipDefaults = true;
2694-
seq.push(exports._doPlot);
2695-
} else {
2696-
for(var componentType in relayoutFlags.arrays) {
2697-
var indices = relayoutFlags.arrays[componentType];
2698-
if(indices.length) {
2699-
var drawOne = Registry.getComponentMethod(componentType, 'drawOne');
2700-
if(drawOne !== Lib.noop) {
2701-
for(var i = 0; i < indices.length; i++) {
2702-
drawOne(gd, indices[i]);
2703-
}
2704-
} else {
2705-
var draw = Registry.getComponentMethod(componentType, 'draw');
2706-
if(draw === Lib.noop) {
2707-
throw new Error('cannot draw components: ' + componentType);
2702+
seq.push(function() {
2703+
return Plots.transitionFromReact(gd, restyleFlags, relayoutFlags, oldFullLayout);
2704+
});
2705+
} else if(restyleFlags.fullReplot || relayoutFlags.layoutReplot) {
2706+
gd._fullLayout._skipDefaults = true;
2707+
seq.push(exports._doPlot);
2708+
} else {
2709+
for(var componentType in relayoutFlags.arrays) {
2710+
var indices = relayoutFlags.arrays[componentType];
2711+
if(indices.length) {
2712+
var drawOne = Registry.getComponentMethod(componentType, 'drawOne');
2713+
if(drawOne !== Lib.noop) {
2714+
for(var i = 0; i < indices.length; i++) {
2715+
drawOne(gd, indices[i]);
2716+
}
2717+
} else {
2718+
var draw = Registry.getComponentMethod(componentType, 'draw');
2719+
if(draw === Lib.noop) {
2720+
throw new Error('cannot draw components: ' + componentType);
2721+
}
2722+
draw(gd);
27082723
}
2709-
draw(gd);
27102724
}
27112725
}
2712-
}
27132726

2714-
seq.push(Plots.previousPromises);
2715-
if(restyleFlags.style) seq.push(subroutines.doTraceStyle);
2716-
if(restyleFlags.colorbars || relayoutFlags.colorbars) seq.push(subroutines.doColorBars);
2717-
if(relayoutFlags.legend) seq.push(subroutines.doLegend);
2718-
if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles);
2719-
if(relayoutFlags.axrange) addAxRangeSequence(seq);
2720-
if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout);
2721-
if(relayoutFlags.modebar) seq.push(subroutines.doModeBar);
2722-
if(relayoutFlags.camera) seq.push(subroutines.doCamera);
2723-
seq.push(emitAfterPlot);
2724-
}
2727+
seq.push(Plots.previousPromises);
2728+
if(restyleFlags.style) seq.push(subroutines.doTraceStyle);
2729+
if(restyleFlags.colorbars || relayoutFlags.colorbars) seq.push(subroutines.doColorBars);
2730+
if(relayoutFlags.legend) seq.push(subroutines.doLegend);
2731+
if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles);
2732+
if(relayoutFlags.axrange) addAxRangeSequence(seq);
2733+
if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout);
2734+
if(relayoutFlags.modebar) seq.push(subroutines.doModeBar);
2735+
if(relayoutFlags.camera) seq.push(subroutines.doCamera);
2736+
seq.push(emitAfterPlot);
2737+
}
27252738

2726-
seq.push(
2727-
Plots.rehover,
2728-
Plots.redrag,
2729-
Plots.reselect
2730-
);
2739+
seq.push(
2740+
Plots.rehover,
2741+
Plots.redrag,
2742+
Plots.reselect
2743+
);
27312744

2732-
plotDone = Lib.syncOrAsync(seq, gd);
2733-
if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd);
2745+
plotDone = Lib.syncOrAsync(seq, gd);
2746+
if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd);
2747+
}
27342748
}
27352749

2736-
return plotDone.then(function() {
2737-
gd.emit('plotly_react', {
2738-
data: data,
2739-
layout: layout
2740-
});
2750+
return plotDone.then(() => {
2751+
if (!configChanged) gd.emit('plotly_react', { config, data, layout });
27412752

27422753
return gd;
27432754
});
@@ -3675,11 +3686,11 @@ function makePlotFramework(gd) {
36753686
// The plot container should always take the full with the height of its
36763687
// parent (the graph div). This ensures that for responsive plots
36773688
// without a height or width set, the paper div will take up the full
3678-
// height & width of the graph div.
3689+
// height & width of the graph div.
36793690
// So, for responsive plots without a height or width set, if the plot
36803691
// container's height is left to 'auto', its height will be dictated by
36813692
// its childrens' height. (The plot container's only child is the paper
3682-
// div.)
3693+
// div.)
36833694
// In this scenario, the paper div's height will be set to 100%,
36843695
// which will be 100% of the plot container's auto height. That is
36853696
// meaninglesss, so the browser will use the paper div's children to set

‎test/jasmine/tests/plot_api_react_test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,13 +425,15 @@ describe('@noCIdep Plotly.react', function() {
425425
.then(function() {
426426
expect(d3SelectAll('.drag').size()).toBe(0);
427427
expect(d3SelectAll('.gtitle').size()).toBe(0);
428+
expect(d3SelectAll('.gtitle-subtitle').size()).toBe(0);
428429
countCalls({plot: 1});
429430

430431
return Plotly.react(gd, data, layout, {});
431432
})
432433
.then(function() {
433434
expect(d3SelectAll('.drag').size()).toBe(11);
434435
expect(d3SelectAll('.gtitle').size()).toBe(0);
436+
expect(d3SelectAll('.gtitle-subtitle').size()).toBe(0);
435437
countCalls({plot: 1});
436438
})
437439
.then(done, done.fail);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /