Skip to content

Conditional widgets in same Row render the wrong branch despite correct underlying data #7523

Description

@bgabdullin-design

Can we access your project?

  • I give permission for members of the FlutterFlow team to access and test my project for the sole purpose of investigating this issue.

Current Behavior

FlutterFlow Bug Report — Conditional widgets in a Row render the wrong branch
Project: ZhenilKey (formerly "EasyKey"), project ID easy-key-ehowpz
Component: BookingPlaceItem (custom component, used as a list item inside a ListView on the "My Bookings" page)
Generated file: booking_place_item_widget.dart (as shown in FlutterFlow's Developer Menu → View Code)
Builder mode: Widget Tree / Test Mode (legacy Test Mode, fresh from-scratch compiles — not Instant Reload)

  1. Summary of the bug
    Inside BookingPlaceItem, a single Row contains two buttons that are each meant to appear only for one specific booking status:
    Button ("Cancel Booking") — should render only when status == upcoming
    ButtonRecordVideoCheckout ("Record Checkout Video") — should render only when status == ongoing
    For a real Firestore booking document whose status field is "ongoing", the wrong button renders (the "Cancel Booking" button, which is gated on upcoming), and the correct button (ButtonRecordVideoCheckout, gated on ongoing) does not render — an empty gap appears in its place instead.
    This happens even though:
    The document's status field is genuinely "ongoing" (confirmed multiple ways, see §2).
    The visibility conditions on both buttons, read directly from the widget tree / generated code, are correct and mutually exclusive (see §4).
    The bug reproduces identically after replacing the conditional-rendering implementation with a structurally different FlutterFlow construct (see §3, item 4).
  2. Confirmation that the underlying data is correct
    Three temporary debug Text widgets were added inside the exact same Row/card as the two buttons, bound directly to the same component parameter (bookingRefDoc) that the button conditions use:
    bookingRefDoc.status.name → prints "ongoing"
    bookingRefDoc.status == Booking.ongoing (boolean) → prints "true"
    A custom debug function getBookingIsOngoingDebug → prints "ongoing"
    All three debug texts render inside the same bordered card as the misbehaving buttons (confirmed via a tight, zoomed screenshot of the single card), so there is no ambiguity about which list item/card is being inspected. The real, live status is unambiguously "ongoing" for the card that nonetheless shows the "Cancel Booking" button instead of "Record Checkout Video".

Expected Behavior

The button gated on status == ongoing (ButtonRecordVideoCheckout) should render when the underlying Firestore document's status field is genuinely "ongoing", instead of the button gated on status == upcoming.

Steps to Reproduce

  1. What has already been checked and ruled out
    Firestore Security Rules — the booking document is fully readable; the status field is visible both in the Firebase console and via the in-app debug text widgets described above. No rule is masking or altering the field.
    Query / document caching — retested with a completely fresh Test Mode session (full from-scratch compile: "Configuring build settings…" → "Checking for dependency conflicts…" → "Compiling your project source code…"), not an Instant Reload. The bug reproduces identically on a clean compile, ruling out a stale cached document snapshot.
    Stale build / stale session — same as above; reproduced on multiple independent from-scratch Test Mode builds, in new debug sessions each time.
    Recomputation of the condition using a different widget-tree construct ("Row recomputation") — the original if (...) Expanded(child: ...) pattern inside the Row's children list was replaced with two separate, explicit ConditionalBuilder widgets (IF <condition> THEN <widget> ELSE <widget>), a structurally different FlutterFlow code-generation path. Both ConditionalBuilders were individually re-opened and verified in the builder UI to have exactly the intended condition and argument binding:
    ConditionalBuilder Pages can be renamed to invalid names #1: IF getBookingStatusName(a) == 'upcoming' THEN Button ELSE Container, argument bookingRefbookingRefDoc
    ConditionalBuilder Radio button initial value is blank #2: IF getBookingStatusName(a) == 'ongoing' THEN ButtonRecordVideoCheckout ELSE Container, argument bookingRefbookingRefDoc
    The bug reproduced identically with this alternate implementation: the "ongoing" card still showed the Cancel button and an empty Container in place of the video button.
    Precomputing the condition into a separate variable instead of calling the custom function inline inside each condition — no change in behavior.
    Flutter Key uniqueness — each list item has a unique key: Key('Key431_${listViewBookingRecord.reference.id}'), ruling out ListView element-recycling/key-collision as the cause.
    The custom function itself — getBookingStatusName is pure, single-line, and deterministic, with no caching:
   String? getBookingStatusName(BookingRecord? bookingRef) {
     return bookingRef?.status?.name;
   }

Other overrides — a project-wide search for getBookingStatusName shows only 3 usages: the Cancel-button condition, the Record-Video-button condition, and one debug Text widget. No hidden per-instance property override exists elsewhere.
4. Exact source locations (generated code)
File: booking_place_item_widget.dart (component BookingPlaceItem)
Lines ~220–222 — "Cancel Booking" button condition:

  if (functions.getBookingStatusName(widget!.bookingRefDoc) ==
      Booking.upcoming.name)
    Expanded(
      child: FFButtonWidget(...CancelBookingWidget...),
    ),

Lines ~272–274 — "Record Checkout Video" button condition:

  if (functions.getBookingStatusName(widget!.bookingRefDoc) ==
      Booking.ongoing.name)
    Expanded(
      child: FFButtonWidget(...selectMedia(isVideo:true)...),
    ),

Lines ~415–421 — a third, unrelated conditional in the same widget (Cancelled → "Re-Book" button, resets status to upcoming), included for completeness since it lives in the same file/widget tree.
(Line numbers are as shown in FlutterFlow's Developer Menu → View Code panel at the time of inspection; they may shift slightly if the component is edited further.)
Widget instantiation (from the parent my_booking_widget.dart, for reference — confirms unique keying per list item):

child: wrapWithModel(
  model: _model.bookingPlaceItemModels1.getModel(
    listViewBookingRecord.reference.id,
    listViewIndex,
  ),
  updateCallback: () => safeSetState(() {}),
  updateOnChange: true,
  child: BookingPlaceItemWidget(
    key: Key('Key431_${listViewBookingRecord.reference.id}'),
    bookingRefDoc: listViewBookingRecord,
  ),
),
  1. Impact
    Users with an "ongoing" booking cannot see or tap the "Record Checkout Video" button, which is required to complete their checkout video recording, and are instead shown an irrelevant "Cancel Booking" action for a booking that is already in progress. This blocks the app's core checkout flow for any booking currently marked "ongoing".
  2. Request
    Given that both the underlying data and both possible widget-tree implementations of the conditional rendering have been verified correct through multiple independent checks, this appears to be a FlutterFlow platform/code-generation issue affecting conditional widget visibility within a Row, rather than a project-configuration mistake. We would appreciate the FlutterFlow team's help reproducing and investigating this, and can provide project access / a shareable Test Mode link on request.

Reproducible from Blank

  • The steps to reproduce above start from a blank project.

Bug Report Code (Required)

ITFfk/Lqx8pgoflc0a6JdcJF9WMWOWUcTeU30+thcw4bI+PxOoY2OffRQEptWOqHY1ZmI2GgpE4Cw636iIbPKMArPQSrfqJzyahTUxDjcGK6VpvTPJbtY0d6TMBVJ2qM0abQuglvIulvLVI92DmmItiub3qCf9qOYwx5e6fDbOY=

Visual documentation

Image Image

Environment

- FlutterFlow version: FlutterFlow v7.0.81
- Platform: Web
- Browser name and version: Chrome (last version)
- Operating system and version affected: Windows

Additional Information

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: needs triageA potential issue that has not been confirmed as a bug.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions