Commit e7b9082fdd0 for woocommerce
commit e7b9082fdd0f77fad08647abf5d8504b2fb31bb5
Author: Amit Raj <77401999+amitraj2203@users.noreply.github.com>
Date: Sat May 2 01:15:02 2026 +0530
Migrate Catalog Sorting Block to use iAPI (#62854)
* Add interactivity support and frontend store logic in catalog sorting block
* Refactor catalog sorting block to utilize Interactivity API
* Add changelog file
* Fix lint error
* Use `WP HTML Tag Processor` to inject directives
* Add iAPI related tests for CatalogSorting block
* Add conditional validation for iAPI
* Refactor CatalogSorting block to use current window URL for sorting updates
* Lock the store
* Use withSyncEvent for preventSubmit and handleSortChange
* remove client-side navigation checks
* Remove unused BlocksSharedState import and related code from CatalogSorting class
---------
Co-authored-by: Brandon Kraft <public@brandonkraft.com>
diff --git a/plugins/woocommerce/changelog/60314-migrate-catalog-sorting-block-iapi b/plugins/woocommerce/changelog/60314-migrate-catalog-sorting-block-iapi
new file mode 100644
index 00000000000..44696b8bab1
--- /dev/null
+++ b/plugins/woocommerce/changelog/60314-migrate-catalog-sorting-block-iapi
@@ -0,0 +1,4 @@
+Significance: minor
+Type: enhancement
+
+Migrate the Catalog Sorting block to use Interactivity API
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/catalog-sorting/block.json b/plugins/woocommerce/client/blocks/assets/js/blocks/catalog-sorting/block.json
index 93219fc6f51..3085af2d194 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/catalog-sorting/block.json
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/catalog-sorting/block.json
@@ -5,9 +5,7 @@
"category": "woocommerce",
"keywords": [ "WooCommerce" ],
"supports": {
- "interactivity": {
- "clientNavigation": true
- },
+ "interactivity": true,
"color": {
"text": true,
"background": false
@@ -16,6 +14,7 @@
"fontSize": true
}
},
+ "viewScriptModule": "woocommerce/catalog-sorting",
"attributes": {
"fontSize": {
"type": "string",
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/catalog-sorting/frontend.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/catalog-sorting/frontend.ts
new file mode 100644
index 00000000000..e77ff5f1b57
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/catalog-sorting/frontend.ts
@@ -0,0 +1,44 @@
+/**
+ * External dependencies
+ */
+import { store, withSyncEvent } from '@wordpress/interactivity';
+
+const BLOCK_NAME = 'woocommerce/catalog-sorting';
+
+const catalogSortingStore = {
+ actions: {
+ /**
+ * Prevent default form submission.
+ */
+ preventSubmit: withSyncEvent( ( event: Event ) => {
+ event.preventDefault();
+ } ),
+
+ /**
+ * Handle sort order change.
+ */
+ handleSortChange: withSyncEvent( function* ( event: Event ): Generator {
+ // Stop propagation to prevent jQuery handler from seeing the event.
+ event.stopPropagation();
+
+ const target = event.target as HTMLSelectElement;
+ const newOrderBy = target.value;
+
+ // Build URL with updated orderby parameter.
+ const url = new URL( window.location.href );
+
+ url.searchParams.set( 'orderby', newOrderBy );
+ url.searchParams.set( 'paged', '1' );
+
+ // Client-side navigation.
+ const routerModule: typeof import('@wordpress/interactivity-router') =
+ yield import( '@wordpress/interactivity-router' );
+
+ yield routerModule.actions.navigate( url.href );
+ } ),
+ },
+};
+
+store( BLOCK_NAME, catalogSortingStore, {
+ lock: true,
+} );
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/CatalogSorting.php b/plugins/woocommerce/src/Blocks/BlockTypes/CatalogSorting.php
index 71796c57e4e..be39d3c118a 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/CatalogSorting.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/CatalogSorting.php
@@ -35,6 +35,22 @@ class CatalogSorting extends AbstractBlock {
return;
}
+ // Use WP_HTML_Tag_Processor to inject Interactivity API directives.
+ $processor = new \WP_HTML_Tag_Processor( $catalog_sorting );
+
+ // Find and modify the form element.
+ if ( $processor->next_tag( array( 'tag_name' => 'form' ) ) ) {
+ $processor->set_attribute( 'data-wp-interactive', 'woocommerce/catalog-sorting' );
+ $processor->set_attribute( 'data-wp-on--submit', 'actions.preventSubmit' );
+ }
+
+ // Find and modify the select element.
+ if ( $processor->next_tag( array( 'tag_name' => 'select' ) ) ) {
+ $processor->set_attribute( 'data-wp-on--change', 'actions.handleSortChange' );
+ }
+
+ $catalog_sorting = $processor->get_updated_html();
+
$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes, array(), array( 'extra_classes' ) );
$wrapper_attributes = get_block_wrapper_attributes(
array(
@@ -57,13 +73,4 @@ class CatalogSorting extends AbstractBlock {
$catalog_sorting
);
}
-
- /**
- * Get the frontend script handle for this block type.
- *
- * @param string $key Data to get, or default to everything.
- */
- protected function get_block_type_script( $key = null ) {
- return null;
- }
}
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/CatalogSorting.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/CatalogSorting.php
index e1b3703333d..2c9ae0015cb 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/CatalogSorting.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypes/CatalogSorting.php
@@ -9,9 +9,12 @@ namespace Automattic\WooCommerce\Tests\Blocks\BlockTypes;
*/
class CatalogSorting extends \WP_UnitTestCase {
/**
- * Tests that the Catalog Sorting block has the correct font size based on the default style attribute.
+ * Set up test fixtures.
*/
- public function test_catalog_sorting_has_small_font_size() {
+ public function setUp(): void {
+ parent::setUp();
+
+ // Create a test product and set up loop.
$temp_product = \WC_Helper_Product::create_simple_product();
$temp_product->set_name( 'Test Product' );
$temp_product->save();
@@ -21,8 +24,46 @@ class CatalogSorting extends \WP_UnitTestCase {
wc_set_loop_prop( 'total', 1 );
wc_set_loop_prop( 'per_page', 1 );
wc_set_loop_prop( 'current_page', 1 );
+ }
+ /**
+ * Tests that the Catalog Sorting block has the correct font size based on the default style attribute.
+ */
+ public function test_catalog_sorting_has_small_font_size() {
$markup = do_blocks( '<!-- wp:woocommerce/catalog-sorting /-->' );
$this->assertStringContainsString( 'has-small-font-size', $markup, 'The Catalog Sorting block has the correct font size.' );
}
+
+ /**
+ * Tests that Interactivity API directive is added to the form element.
+ */
+ public function test_form_has_interactive_directive() {
+ $markup = do_blocks( '<!-- wp:woocommerce/catalog-sorting /-->' );
+ $this->assertStringContainsString( 'data-wp-interactive="woocommerce/catalog-sorting"', $markup, 'Form should have data-wp-interactive directive.' );
+ }
+
+ /**
+ * Tests that form submit prevention directive is added to the form element.
+ */
+ public function test_form_has_submit_prevention_directive() {
+ $markup = do_blocks( '<!-- wp:woocommerce/catalog-sorting /-->' );
+ $this->assertStringContainsString( 'data-wp-on--submit="actions.preventSubmit"', $markup, 'Form should have submit prevention directive.' );
+ }
+
+ /**
+ * Tests that change handler directive is added to the select element.
+ */
+ public function test_select_has_change_handler_directive() {
+ $markup = do_blocks( '<!-- wp:woocommerce/catalog-sorting /-->' );
+ $this->assertStringContainsString( 'data-wp-on--change="actions.handleSortChange"', $markup, 'Select should have change handler directive.' );
+ }
+
+ /**
+ * Tests that the block renders without errors when no products exist.
+ */
+ public function test_renders_empty_when_no_pagination() {
+ wc_set_loop_prop( 'is_paginated', false );
+ $markup = do_blocks( '<!-- wp:woocommerce/catalog-sorting /-->' );
+ $this->assertEmpty( trim( $markup ), 'Block should not render when pagination is disabled.' );
+ }
}