Byron94odhiambo opened a new pull request, #61665:
URL: https://github.com/apache/airflow/pull/61665

   <h2>Summary</h2>
   <p>This PR adds support for cascading (dependent) dropdown parameters in the 
Trigger DAG form. When a user selects a value in a parent dropdown, child 
dropdowns automatically filter to show only the relevant options.</p>
   <h2>Usage</h2>
   <pre><code class="language-python">from airflow.sdk.definitions.param import 
Param
   
   with DAG(
       "my_dag",
       params={
           "country": Param("Kenya", type="string", enum=["Kenya", "Ethiopia", 
"Tanzania"]),
           "region": Param(
               "Nandi County",
               type="string",
               depends_on="country",
               options_map={
                   "Kenya": ["Nandi County", "Nyandarua", "Nakuru", "Kiambu"],
                   "Ethiopia": ["Jimma", "Arsi", "Bale", "Sidama"],
                   "Tanzania": ["Arusha", "Dodoma", "Mwanza", "Tanga"],
               },
           ),
           "city": Param(
               "Kapsabet",
               type="string",
               depends_on="region",
               options_map={
                   "Nandi County": ["Kapsabet", "Nandi Hills", "Mosoriot"],
                   "Nyandarua": ["Ol Kalou", "Engineer", "Ndaragwa"],
                   # ... more mappings
               },
           ),
       },
   ) as dag:
       ...
   </code></pre>
   <h2>How It Works</h2>
   <ul>
   <li><strong><code>depends_on</code></strong>: Names the parent parameter 
whose value controls this dropdown's options.</li>
   <li><strong><code>options_map</code></strong>: A dict mapping each parent 
value to the list of allowed child options.</li>
   <li>When the parent value changes, the child dropdown filters to show only 
matching options and auto-resets if the current selection is no longer 
valid.</li>
   <li>Multi-level cascading is supported (e.g., country → region → city).</li>
   </ul>
   <h2>Changes</h2>
   
   Layer | File | What
   -- | -- | --
   SDK | task-sdk/src/airflow/sdk/definitions/param.py | Add depends_on + 
options_map attrs to Param, auto-populate enum from options_map, preserve 
through copy/dump/serialize/deserialize
   Serialization | airflow-core/src/airflow/serialization/serialized_objects.py 
| Persist depends_on/options_map through DB serialization round-trip
   Serialization | airflow-core/src/airflow/serialization/definitions/param.py 
| Add SerializedParam support for cascading fields
   Frontend | 
airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldDropdown.tsx | 
Compute effectiveEnum from parent value, auto-reset invalid child values
   Frontend | airflow-core/src/airflow/ui/src/queries/useDagParams.ts | Add 
depends_on/options_map to ParamSpec type
   Frontend | airflow-core/src/airflow/ui/src/queries/useParamStore.ts | 
Preserve cascading fields through param store rebuilds
   Example | 
airflow-core/src/airflow/example_dags/example_params_cascading_dropdown.py | 
3-level cascade demo DAG (country → region → city)
   Tests | task-sdk/tests/test_param_cascading.py | 16 unit tests covering all 
cascading scenarios
   
   
   <h2>Testing</h2>
   <h3>Backend</h3>
   <pre><code class="language-bash">python -m pytest 
task-sdk/tests/test_param_cascading.py -v --noconftest -o "asyncio_mode=auto" 
-o "addopts="
   # 16/16 PASSED ✅
   </code></pre>
   <h3>Frontend</h3>
   <ol>
   <li>Start Airflow: <code>airflow standalone</code></li>
   <li>Open http://localhost:8080</li>
   <li>Find <strong>"Cascading Params Example"</strong> DAG</li>
   <li>Click <strong>Trigger</strong> to open the parameter form</li>
   <li>Change <strong>Country</strong> → Region dropdown filters to matching 
regions</li>
   <li>Change <strong>Region</strong> → City dropdown filters to matching 
cities</li>
   </ol>
   <h3>Validation</h3>
   <ul>
   <li><code>depends_on</code> without <code>options_map</code> raises 
<code>TypeError</code></li>
   <li><code>options_map</code> without <code>depends_on</code> raises 
<code>TypeError</code></li>
   <li><code>options_map</code> values must be lists</li>
   <li>Non-cascading params are completely unaffected</li>
   <li>Cascading metadata survives serialize → DB → deserialize → API 
round-trip</li>
   </ul></body></html>


-- 
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