feat: hide model_family on Stack/Combo when flake_data is connected (#216)

The previous attempt (#204 / 36620bd) only set `widget.hidden = true`,
`widget.type = "hidden"`, and zeroed computeSize. On the modern ComfyUI
frontend these flags are not enough — the canvas-drawn COMBO widget
still renders. Result: the model_family dropdown stayed visible on
FlakeStack and FlakeCombo even when an upstream flake_data pin was
connected.

Detach the widget entirely from node.widgets when the input is
connected (saving its prior index so it can be re-inserted in place
when disconnected) and re-add it on disconnect. Also drop the
DOM-querying `_getFamilyWidgetEl` fallback — it relied on label text
that doesn't exist in canvas-drawn widgets and never worked. Run an
initial sync at setup so loaded workflows hide the widget on open
without waiting for the 200ms poll.

Closes #216
This commit is contained in:
Mehdi Chaid
2026-05-20 18:37:10 -04:00
parent 482c8cfdee
commit 2db236a8a8
2 changed files with 65 additions and 92 deletions
+32 -46
View File
@@ -288,62 +288,48 @@ export function setupFlakeComboWidget(node) {
}
// Hide model_family widget when flake_data input is connected, and infer
// the family value from the upstream node.
let _familyWidgetVisible = true;
function _getFamilyWidgetEl() {
if (!familyWidget) return null;
if (familyWidget.element) return familyWidget.element;
if (familyWidget.inputEl) return familyWidget.inputEl;
const nodeEl = node.htmlEl || node.element;
if (!nodeEl) return null;
const allEls = nodeEl.querySelectorAll("label, span, div");
for (const el of allEls) {
const text = el.textContent || "";
if (text.includes("model_family") || text.includes("Model Family") || text.includes("model family")) {
const container = el.closest(".comfy-widget, .litegraph-widget, [class*='widget']");
return container || el;
}
}
return null;
// the family value from the upstream node. We detach the widget entirely
// from node.widgets so it cannot be rendered by either LiteGraph or the
// modern ComfyUI frontend (setting type/hidden alone is not enough on
// recent frontend versions).
let _familyHidden = false;
function _inferUpstreamFamily() {
const flakeDataInput = node.inputs?.find(i => i.name === "flake_data");
if (!flakeDataInput || flakeDataInput.link == null) return null;
const link = node.graph?.links?.[flakeDataInput.link];
if (!link) return null;
const upstreamNode = node.graph.getNodeById(link.origin_id);
if (!upstreamNode) return null;
const upstreamFamily = upstreamNode.widgets?.find(w => w.name === "model_family");
return upstreamFamily?.value || null;
}
function _updateFamilyVisibility() {
if (!familyWidget) return;
const flakeDataInput = node.inputs.find(i => i.name === "flake_data");
const isConnected = flakeDataInput && flakeDataInput.link != null;
if (isConnected) {
const link = node.graph.links[flakeDataInput.link];
if (link) {
const upstreamNode = node.graph.getNodeById(link.origin_id);
if (upstreamNode) {
const upstreamFamily = upstreamNode.widgets?.find(w => w.name === "model_family");
if (upstreamFamily && upstreamFamily.value !== familyWidget.value) {
familyWidget.value = upstreamFamily.value;
if (familyWidget.callback) familyWidget.callback(upstreamFamily.value);
}
}
const upstream = _inferUpstreamFamily();
const shouldHide = upstream !== null;
if (shouldHide && upstream !== familyWidget.value) {
familyWidget.value = upstream;
if (familyWidget.callback) familyWidget.callback(upstream);
}
if (shouldHide === _familyHidden) return;
_familyHidden = shouldHide;
if (shouldHide) {
const idx = node.widgets?.indexOf(familyWidget) ?? -1;
if (idx >= 0) {
node._familyWidgetSavedIndex = idx;
node.widgets.splice(idx, 1);
}
}
if (isConnected === _familyWidgetVisible) return;
_familyWidgetVisible = isConnected;
const el = _getFamilyWidgetEl();
if (el) {
el.style.display = isConnected ? "none" : "";
const parent = el.closest(".comfy-widget, .litegraph-widget, [class*='widget']");
if (parent && parent !== el) parent.style.display = isConnected ? "none" : "";
}
if (isConnected) {
familyWidget.computeSize = () => [0, -4];
familyWidget.type = "hidden";
familyWidget.hidden = true;
} else {
familyWidget.computeSize = undefined;
familyWidget.type = "combo";
familyWidget.hidden = false;
if (!node.widgets.includes(familyWidget)) {
const idx = Math.min(node._familyWidgetSavedIndex ?? 0, node.widgets.length);
node.widgets.splice(idx, 0, familyWidget);
}
}
node.setSize(node.computeSize());
node.setDirtyCanvas(true, true);
}
const _familyPoll = setInterval(_updateFamilyVisibility, 200);
_updateFamilyVisibility();
if (!node.properties) node.properties = {};
if (!node.properties._combo_flakes) node.properties._combo_flakes = [];
+33 -46
View File
@@ -312,62 +312,49 @@ export function setupFlakeWidget(node) {
}
// Hide model_family widget when flake_data input is connected, and infer
// the family value from the upstream node.
let _familyWidgetVisible = true;
function _getFamilyWidgetEl() {
if (!familyWidget) return null;
if (familyWidget.element) return familyWidget.element;
if (familyWidget.inputEl) return familyWidget.inputEl;
const nodeEl = node.htmlEl || node.element;
if (!nodeEl) return null;
const allEls = nodeEl.querySelectorAll("label, span, div");
for (const el of allEls) {
const text = el.textContent || "";
if (text.includes("model_family") || text.includes("Model Family") || text.includes("model family")) {
const container = el.closest(".comfy-widget, .litegraph-widget, [class*='widget']");
return container || el;
}
}
return null;
// the family value from the upstream node. We detach the widget entirely
// from node.widgets so it cannot be rendered by either LiteGraph or the
// modern ComfyUI frontend (setting type/hidden alone is not enough on
// recent frontend versions).
let _familyHidden = false;
function _inferUpstreamFamily() {
const flakeDataInput = node.inputs?.find(i => i.name === "flake_data");
if (!flakeDataInput || flakeDataInput.link == null) return null;
const link = node.graph?.links?.[flakeDataInput.link];
if (!link) return null;
const upstreamNode = node.graph.getNodeById(link.origin_id);
if (!upstreamNode) return null;
const upstreamFamily = upstreamNode.widgets?.find(w => w.name === "model_family");
return upstreamFamily?.value || null;
}
function _updateFamilyVisibility() {
if (!familyWidget) return;
const flakeDataInput = node.inputs.find(i => i.name === "flake_data");
const isConnected = flakeDataInput && flakeDataInput.link != null;
if (isConnected) {
const link = node.graph.links[flakeDataInput.link];
if (link) {
const upstreamNode = node.graph.getNodeById(link.origin_id);
if (upstreamNode) {
const upstreamFamily = upstreamNode.widgets?.find(w => w.name === "model_family");
if (upstreamFamily && upstreamFamily.value !== familyWidget.value) {
familyWidget.value = upstreamFamily.value;
if (familyWidget.callback) familyWidget.callback(upstreamFamily.value);
}
}
const upstream = _inferUpstreamFamily();
const shouldHide = upstream !== null;
if (shouldHide && upstream !== familyWidget.value) {
familyWidget.value = upstream;
if (familyWidget.callback) familyWidget.callback(upstream);
}
if (shouldHide === _familyHidden) return;
_familyHidden = shouldHide;
if (shouldHide) {
const idx = node.widgets?.indexOf(familyWidget) ?? -1;
if (idx >= 0) {
node._familyWidgetSavedIndex = idx;
node.widgets.splice(idx, 1);
}
}
if (isConnected === _familyWidgetVisible) return;
_familyWidgetVisible = isConnected;
const el = _getFamilyWidgetEl();
if (el) {
el.style.display = isConnected ? "none" : "";
const parent = el.closest(".comfy-widget, .litegraph-widget, [class*='widget']");
if (parent && parent !== el) parent.style.display = isConnected ? "none" : "";
}
if (isConnected) {
familyWidget.computeSize = () => [0, -4];
familyWidget.type = "hidden";
familyWidget.hidden = true;
} else {
familyWidget.computeSize = undefined;
familyWidget.type = "combo";
familyWidget.hidden = false;
if (!node.widgets.includes(familyWidget)) {
const idx = Math.min(node._familyWidgetSavedIndex ?? 0, node.widgets.length);
node.widgets.splice(idx, 0, familyWidget);
}
}
node.setSize(node.computeSize());
node.setDirtyCanvas(true, true);
}
const _familyPoll = setInterval(_updateFamilyVisibility, 200);
// Also run once synchronously so loaded workflows hide the widget on open.
_updateFamilyVisibility();
function readEntries() {
try {