Skip to content

Conversation

@anshuksi282-ksolves
Copy link
Contributor

closes: #54800

Description

This PR restores and enhances the ability to pre-populate the Trigger DAG and Backfill forms via URL query parameters in the Airflow 3.0 UI. This feature existed in Airflow 2.x and is useful for sharing pre-configured run links.

Key Changes:

  1. URL Param Parsing:

    • Implemented using the useSearchParams hook (replacing manual parsing logic from stale PRs).
    • Added a utility getTriggerConf to handle both JSON strings (?conf={"a":1}) and Key-Value pairs (?a=1).
  2. Form Updates:

    • Trigger Form: Supports run_id, logical_date, note, and conf.
    • Backfill Form: Supports from_date, to_date, max_active_runs, reprocess_behavior, and run_backwards.
    • Config Form: Automatically expands the "Advanced Options" accordion if configuration data is present in the URL.
  3. Code Quality:

    • Optimized RunBackfillForm.tsx logic to keep the file size strictly under the 250-line linting limit.
    • Ensured consistent naming conventions for backfill parameters (from_date / to_date) to match the API and UI components.
  4. Documentation:

    • Updated docs/core-concepts/params.rst to document the supported URL parameters and examples.

How to reproduce / Test

You can test this by running the UI and navigating to any DAG (e.g., tutorial) using the following URLs:

1. Trigger Single Run (JSON Config):
The modal should open, fields should be filled, and the JSON editor should show the config.
http://localhost:8080/dags/tutorial/trigger/single?run_id=test_run_01&note=Testing_Note&conf={"environment":"dev","debug":true}

2. Trigger Single Run (Key-Value Config):
The "Advanced Options" should open and show {"foo": "bar"}.
http://localhost:8080/dags/tutorial/trigger/single?foo=bar&retry=3

3. Backfill Form:
The Backfill form should open with dates, max runs, and the "Run Backwards" checkbox pre-selected.
http://localhost:8080/dags/tutorial/trigger/backfill?from_date=2024-01-01T00:00:00&to_date=2024-01-05T00:00:00&max_active_runs=5&run_backwards=true


^ Add meaningful description above
Read the Pull Request Guidelines for more information.
In case of fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
In case of a new dependency, check compliance with the ASF 3rd Party License Policy.
In case of backwards incompatible changes please leave a note in a newsfragment file, named {pr_number}.significant.rst or {issue_number}.significant.rst, in airflow-core/newsfragments.

Copy link
Contributor

@jscheffl jscheffl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Looks clear and good for me.

I tried but the trigger form was not opening. Don't know if I mis-understood but I needed to click the "trigger" button to open the form pre-populated. Otherwise working fine. I'd expected it is oepning pre-populated when calling with a prepared/pre-filled URL.

@anshuksi282-ksolves
Copy link
Contributor Author

PR Looks clear and good for me.

I tried but the trigger form was not opening. Don't know if I mis-understood but I needed to click the "trigger" button to open the form pre-populated. Otherwise working fine. I'd expected it is oepning pre-populated when calling with a prepared/pre-filled URL.

Hi @jscheffl Thanks for catching that! You are correct, I missed wiring the URL state to the modal visibility logic in the initial commit.

I have pushed a fix in the latest commit (Overview.tsx) where I check for the mode parameter in the URL. Now, if the URL contains /trigger/single or /trigger/backfill, the modal will open automatically with the pre-populated values.

@jscheffl
Copy link
Contributor

Thanks for the rework. I was testing and it seems there is a bit of a glitch because the two-way synchronization of the UI gets broken if not all parameters are passed in the UI trigger URL.

For example using http://localhost:28080/dags/example_params_ui_tutorial/trigger/single?number_param=77 is changes the dictionary of the run-conf to the value as passed but the form fields of the trigger form are not updated to be in sync. And even worse, if you click on the form (any element) the JSON dictionary will be back-populated to the form elements and most form elements dis-appear.

So a fix is needed to merge/sync the given parameters of the URL to the default values not to break the form and needs to ensure that updated form values are correctly populated to the UI.

@anshuksi282-ksolves
Copy link
Contributor Author

Hi @jscheffl Thanks for catching this !
I have pushed a fix that addresses the synchronization glitch and the disappearing fields issue.

Changes made:

  • Unified Merge Logic: The form now correctly merges the DAG's default parameters with the incoming URL parameters during initialization. This ensures that defaults are preserved, and only specific fields are overridden by the URL.
  • UI Store Synchronization: I added logic to explicitly update the useParamStore (setParamsDict) alongside the React Hook Form state. This ensures the visual input fields update immediately to reflect the URL values (e.g., showing 77 instead of 10) without requiring a click interaction.
  • Data Cleaning: Implemented a helper to extract clean values from the parameter objects to prevent [object Object] rendering issues.

Please let me know if this looks good to you!

Copy link
Contributor

@jscheffl jscheffl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me this looks good and I am happy that the function is back!

In the past there was always some discussion about excessive use of "useEffect()" so I'd leave this PR open - from my side it is good - but another pair of Web Development knowledge would be good to ensure it is implemented as it should be.

@jscheffl jscheffl added this to the Airflow 3.2.0 milestone Dec 14, 2025
@anshuksi282-ksolves
Copy link
Contributor Author

For me this looks good and I am happy that the function is back!

In the past there was always some discussion about excessive use of "useEffect()" so I'd leave this PR open - from my side it is good - but another pair of Web Development knowledge would be good to ensure it is implemented as it should be.

Thanks @jscheffl for the approval!

I used useEffect to safely sync the async DAG params with URL inputs using react-hook-form's reset() method. This ensures the form updates correctly once data is loaded. That said, I'm happy to refactor if the UI team prefers a different pattern!"

Copy link
Member

@pierrejeambrun pierrejeambrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind rebasing and fixing the merge conflict so we can merge it.

Yes we tend to try to avoid useEffect, but sometimes there's no good way to do that and keep the useEffect.

I think it will be fine for now.

@uranusjr
Copy link
Member

Please also fix CI errors.

@anshuksi282-ksolves
Copy link
Contributor Author

Thanks for the continued review!
I have successfully rebased with main and resolved the conflicts regarding the new UI structure (VStack & DataInterval fields).
Refactor Update:
I noticed that TriggerDAGForm.tsx was exceeding the 250-line limit linting rule after the merge. To adhere to clean code standards, I extracted the business logic into a dedicated utility file:

  • src/utils/trigger.ts: Moved all helper functions (e.g., mergeUrlParams, extractParamValues, getTriggerConf) and Type definitions here.
  • TriggerDAGForm.tsx: Now focuses solely on the UI and Form state, keeping the component lightweight and readable.
  • Tested locally, and the URL parameter syncing is working perfectly with the new UI layout.

Ready for a final look!

@jscheffl
Copy link
Contributor

Oh, still small glitches in static checks. Maybe you run them locally before committing.

Copy link
Contributor

@jscheffl jscheffl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the numerous rework. Did a final test. Looks good for me!

@jscheffl jscheffl merged commit 907b4ef into apache:main Dec 22, 2025
78 checks passed
@jscheffl
Copy link
Contributor

Hi @anshuksi282-ksolves! While working on latest main I realized a regression in the UI caused by inconsistent updates. Can you provide a fix? Else I'd propose to revert this PR and re-apply with a proper fix.

It seems the state management and bi-directional updates are not working anymore reliably.

Steps to re-produce:

  • Open the trigger form for the example Dag "Params UI Tutorial"
  • You see a required field missing, trigger button is not enabled.
  • Expand the "Typed parameters with Param object"
  • Enter at least 10 chars into the "Required text field"
  • Expand the "Advanced options" section and inspect the "Configuration JSON"
  • Attempt to trigger and see the error message, the required field is not submitted.

(In general it seems no change of the form fields updates the JSON configuration in "Advanced options" section anymore and thus any change in the form yields to no effect when triggering.)

Also one nit: I just realized that the "Advanced options" section is always expanded also if the form just has params defined. I understood the diff before as being a feature if a URL param is passed but now realize that the logic also hits when the UI is just opened.

Oh and found another even more error situation, if you have used the dag overview page and search, e.g. Dags for name "params"
image

...then the URL is changed to something like http://localhost:28080/dags?name_pattern=params...
which then if you trigger on the Dag overview page the form will add a parameter for the Dag search parameters from the URL into the form. So in this case parameters should / mus ONLY be parsed if called with /trigger/single and not if the page where the user navigated before contains parameters as well:
image

...okay sorry, as of writing the bug here and ending up in three errors I'm going to revert now. Can you please re-apply the PR with fixes?

Subham-KRLX pushed a commit to Subham-KRLX/airflow that referenced this pull request Jan 2, 2026
…pache#59231)

* Feat: Support URL params for pre-filling Trigger and Backfill forms

* Fix docs build: Correct RST formatting and add 'reprocessed' to wordlist

* Fix auto-open modal and update docs

* Fix: Sync URL params with defaults and update UI store to prevent data loss

* Merge main branch and resolve conflicts

* Refactor: Move TriggerDag types and logic to utils to satisfy line limit
stegololz pushed a commit to stegololz/airflow that referenced this pull request Jan 9, 2026
…pache#59231)

* Feat: Support URL params for pre-filling Trigger and Backfill forms

* Fix docs build: Correct RST formatting and add 'reprocessed' to wordlist

* Fix auto-open modal and update docs

* Fix: Sync URL params with defaults and update UI store to prevent data loss

* Merge main branch and resolve conflicts

* Refactor: Move TriggerDag types and logic to utils to satisfy line limit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UI Related to UI/UX. For Frontend Developers. kind:documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trigger form can be called via URL with fields pre-populated.

4 participants