bbovenzi commented on code in PR #74885:
URL: https://github.com/apache/airflow/pull/74885#discussion_r4484909530


##########
airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx:
##########
@@ -58,6 +79,18 @@ export const FieldDropdown = ({ name, namespace = "default", 
onUpdate }: Flexibl
         ? (options.find((opt) => opt.value === String(param.value)) ?? null)
         : null;
 
+  // A parent change can leave the value outside the new options, so clear it
+  const isStale = dependsOn !== undefined && param.value !== null && 
currentValue === null;
+
+  useEffect(() => {

Review Comment:
   We should avoid unnecessary `useEffect`s. Let's do this as part of the param 
write instead of a separate loop.
   
   ```
   getOptions(param, params, defaults):
       if param has no parent: return param.enum
       parentValue = params[parent].value ?? defaults[parent].value   // conf 
may leave out the parent
       return param.options_map[str(parentValue)] ?? []
   
   clearStale(params, defaults):
       repeat until nothing changes:                // handles chains A → B → C
           for each param with a parent and a non-null value:
               if value not in getOptions(param, params, defaults):
                   param.value = null
       return params
   
   store.setParamsDict(newParams):
       params = clearStale(newParams, initialParams)    // one write, every 
child cleared together
       save params and conf
   
   FieldDropdown:
       options = getOptions(param, params, initialParams)
       // no isStale, no useEffect
   ```



##########
airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx:
##########
@@ -58,6 +79,18 @@ export const FieldDropdown = ({ name, namespace = "default", 
onUpdate }: Flexibl
         ? (options.find((opt) => opt.value === String(param.value)) ?? null)
         : null;
 
+  // A parent change can leave the value outside the new options, so clear it
+  const isStale = dependsOn !== undefined && param.value !== null && 
currentValue === null;
+
+  useEffect(() => {

Review Comment:
   This useEffect will call on every change because paramsDict is always 
different



##########
airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx:
##########
@@ -40,13 +42,32 @@ const labelLookup = (
 
 const enumTypes = ["string", "number", "integer"];
 
+// Python str() of a string, integer, boolean or null parent value, because 
the serialized Dag
+// stores the keys of options_map with str()
+const getOptionKey = (value: unknown): string => {
+  if (value === null || value === undefined) {
+    return "None";
+  }
+  if (typeof value === "boolean") {
+    return value ? "True" : "False";
+  }
+
+  return typeof value === "number" || typeof value === "string" ? 
String(value) : JSON.stringify(value);
+};
+
 export const FieldDropdown = ({ name, namespace = "default", onUpdate }: 
FlexibleFormElementProps) => {
   const { t: translate } = useTranslation("components");
   const { disabled, paramsDict, setParamsDict } = useParamStore(namespace);
   const param = paramsDict[name] ?? paramPlaceholder;
 
+  const { depends_on: dependsOn, options_map: optionsMap } = param.schema;
+  const enumValues =
+    dependsOn === undefined
+      ? param.schema.enum
+      : (optionsMap?.[getOptionKey(paramsDict[dependsOn]?.value)] ?? []);

Review Comment:
   This can force an empty dropdown on a user. We should have a fallback empty 
message or an error message like: "Select {{parent_input}} first"



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to