Skip to content

feat: rewrite interactive table widget in Angular#17416

Open
shuoweil wants to merge 63 commits into
mainfrom
shuowei-angular-rewrite-core
Open

feat: rewrite interactive table widget in Angular#17416
shuoweil wants to merge 63 commits into
mainfrom
shuowei-angular-rewrite-core

Conversation

@shuoweil

@shuoweil shuoweil commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

This PR rewrites the frontend implementation of the interactive TableWidget in Angular, replacing the legacy vanilla JS version (table_widget.js). This enables more structured state management and paves the way for future UI improvements.

Key Changes:

  1. Angular Frontend Rewrite:
    • Created a new Angular application workspace under bigframes/display/table_widget_angular.
    • Introduced WidgetStateService to manage the widget's internal state (pages, sorting, column visibility) and synchronize updates with the Python anywidget model.
    • Rewrote the template, CSS variables (including VS Code dark mode support), pagination controls, and column sorting handlers as Angular components.
    • Compiled and bundled the Angular workspace into the single distribution file table_widget_angular.js, which is now loaded by the Python class.
  2. Backend Refactoring:
    • Renamed DataFrame._get_display_df to _process_display_df and refactored it to return both the processed display DataFrame and its metadata.
    • Updated html.py to standardize representation rendering pipelines, enabling native rendering support for both DataFrame and Series objects.
  3. Robust Multi-Instance Bootstrapping:
    • Configured the Angular bootstrap sequence to use createApplication() and manually attach each component instance to its local widget container (el). This prevents rendering conflicts and state bleeding when rendering multiple widgets on the same notebook page.
  4. Testing:
    • Added a frontend test suite (tests/js/table_widget_angular.test.js) to assert that multiple Angular widgets can bootstrap and render distinct model configurations concurrently.
    • Updated Python backend unit tests under tests/unit/display/ to conform to the new _process_display_df interface.

Verified at: go/scrcast/NTkzNjEzNzYyNDM1NDgxNnw4NTI0NjA5My1iMA
screen/4NJKSkYEjoYjpxA

Fixes #<505414691> 🦕

shuoweil added 30 commits May 4, 2026 23:18
shuoweil added 12 commits May 26, 2026 21:51
# Conflicts:
#	packages/bigframes/bigframes/display/table_widget_angular.js
#	packages/bigframes/bigframes/display/table_widget_angular/README.md
#	packages/bigframes/bigframes/display/table_widget_angular/src/app/app.spec.ts
#	packages/bigframes/bigframes/display/table_widget_angular/src/app/app.ts
# Conflicts:
#	packages/bigframes/bigframes/core/events.py
#	packages/bigframes/bigframes/core/utils.py
#	packages/bigframes/bigframes/session/__init__.py
#	packages/bigframes/bigframes/session/_io/bigquery/__init__.py
#	packages/bigframes/tests/unit/display/test_anywidget.py
#	packages/bigframes/tests/unit/session/test_read_gbq_colab.py
@shuoweil shuoweil self-assigned this Jun 10, 2026
@shuoweil shuoweil requested review from a team as code owners June 10, 2026 21:54
@shuoweil shuoweil requested review from GarrettWu and removed request for a team June 10, 2026 21:54
@shuoweil shuoweil marked this pull request as draft June 10, 2026 21:54

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request transitions the interactive Table Widget frontend for BigQuery DataFrames to a compiled Angular hybrid bundle using anywidget, updating the Python backend to support this integration. Key feedback identifies critical issues, including a missing import of Series in html.py that will cause a runtime NameError, and a bug in the Angular component where extracting column names via textContent includes appended sort indicators, breaking sorting on subsequent clicks. Additionally, it is recommended to remove the initializeHeight logic to let CSS handle the container height dynamically, and to immediately reset the local page signal to 0 in WidgetStateService.setPageSize for UI consistency.

Comment thread packages/bigframes/bigframes/display/html.py Outdated
Comment thread packages/bigframes/bigframes/display/html.py Outdated
Comment thread packages/bigframes/bigframes/display/table_widget_angular/src/app/app.ts Outdated
Comment thread packages/bigframes/bigframes/display/table_widget_angular/src/app/app.ts Outdated
Comment thread packages/bigframes/bigframes/display/table_widget_angular/src/app/app.ts Outdated
Comment thread packages/bigframes/bigframes/display/table_widget_angular/src/app/app.ts Outdated
shuoweil and others added 8 commits June 10, 2026 15:02
…app/widget-state.service.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…app/app.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…app/app.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…app/app.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@shuoweil shuoweil marked this pull request as ready for review June 12, 2026 18:31
@GarrettWu

Copy link
Copy Markdown
Contributor

Is this a feat or refactor?

If it is only "rewriting", then refactor.

)
df = df.assign(**{col: df[col]._apply_unary_op(op) for col in json_cols})
return df
return df, []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the purpose of returning an empty list and then drop it?

)

def _get_display_df(self) -> DataFrame:
def _process_display_df(self) -> tuple[DataFrame, list[str]]:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

don't quite get the meaning of renaming the function.

Though the original name wasn't representative, "process" is more vague than "get".

npm install
```
```bash
ng serve

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does it need any setup to be able to run ng command?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants