Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Filter Products by Attribute: Fix the page reload which happens when clicking the filter button on PHP templates #6287

Merged
merged 8 commits into from
Apr 22, 2022
122 changes: 80 additions & 42 deletions assets/js/blocks/attribute-filter/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,21 +227,74 @@ const AttributeFilterBlock = ( {
[ attributeTerms ]
);

/**
* Appends query params to the current pages URL and redirects them to the new URL for PHP rendered templates.
*
* @param {Object} query The object containing the active filter query.
* @param {boolean} allFiltersRemoved If there are active filters or not.
*/
const redirectPageForPhpTemplate = useCallback(
( query, allFiltersRemoved = false ) => {
if ( allFiltersRemoved ) {
const currentQueryArgKeys = Object.keys(
getQueryArgs( window.location.href )
);

const parsedTaxonomy = parseTaxonomyToGenerateURL(
attributeObject?.taxonomy
);

const url = currentQueryArgKeys.reduce(
( currentUrl, queryArg ) =>
queryArg.includes(
PREFIX_QUERY_ARG_QUERY_TYPE + parsedTaxonomy
) ||
queryArg.includes(
PREFIX_QUERY_ARG_FILTER_TYPE + parsedTaxonomy
)
? removeQueryArgs( currentUrl, queryArg )
: currentUrl,
window.location.href
);

const newUrl = formatParams( url, query );
window.location.href = newUrl;
} else {
const newUrl = formatParams( pageUrl, query );
const currentQueryArgs = getQueryArgs( window.location.href );
const newUrlQueryArgs = getQueryArgs( newUrl );

if ( ! isQueryArgsEqual( currentQueryArgs, newUrlQueryArgs ) ) {
window.location.href = newUrl;
}
}
},
[ pageUrl, attributeObject?.taxonomy ]
);

const onSubmit = useCallback(
( isChecked ) => {
if ( isEditor ) {
return;
}

updateAttributeFilter(
const query = updateAttributeFilter(
productAttributesQuery,
setProductAttributesQuery,
attributeObject,
getSelectedTerms( isChecked ),
blockAttributes.queryType === 'or' ? 'in' : 'and'
);

// This is for PHP rendered template filtering only.
if ( filteringForPhpTemplate && hasSetPhpFilterDefaults ) {
redirectPageForPhpTemplate( query, isChecked.length === 0 );
}
},
[
hasSetPhpFilterDefaults,
filteringForPhpTemplate,
redirectPageForPhpTemplate,
isEditor,
productAttributesQuery,
setProductAttributesQuery,
Expand Down Expand Up @@ -392,49 +445,25 @@ const AttributeFilterBlock = ( {
hasSetPhpFilterDefaults,
} )
) {
setChecked( [] );
const currentQueryArgKeys = Object.keys(
getQueryArgs( window.location.href )
);

const parsedTaxonomy = parseTaxonomyToGenerateURL(
attributeObject?.taxonomy
);

const url = currentQueryArgKeys.reduce(
( currentUrl, queryArg ) =>
queryArg.includes(
PREFIX_QUERY_ARG_QUERY_TYPE + parsedTaxonomy
) ||
queryArg.includes(
PREFIX_QUERY_ARG_FILTER_TYPE + parsedTaxonomy
)
? removeQueryArgs( currentUrl, queryArg )
: currentUrl,
window.location.href
);

const newUrl = formatParams( url, productAttributesQuery );
window.location.href = newUrl;
if ( ! blockAttributes.showFilterButton ) {
setChecked( [] );
redirectPageForPhpTemplate( productAttributesQuery, true );
}
}

setChecked( checked );
const newUrl = formatParams( pageUrl, productAttributesQuery );
const currentQueryArgs = getQueryArgs( window.location.href );
const newUrlQueryArgs = getQueryArgs( newUrl );

if ( ! isQueryArgsEqual( currentQueryArgs, newUrlQueryArgs ) ) {
window.location.href = newUrl;
if ( ! blockAttributes.showFilterButton ) {
setChecked( checked );
redirectPageForPhpTemplate( productAttributesQuery, false );
}
}
}, [
hasSetPhpFilterDefaults,
redirectPageForPhpTemplate,
filteringForPhpTemplate,
productAttributesQuery,
attributeObject,
checked,
blockAttributes.queryType,
pageUrl,
hasSetPhpFilterDefaults,
blockAttributes.showFilterButton,
] );

/**
Expand All @@ -445,24 +474,33 @@ const AttributeFilterBlock = ( {
*/
useEffect( () => {
if ( filteringForPhpTemplate ) {
const activeFilters = getActiveFilters(
filteringForPhpTemplate, attributeObject
);
if (
checked.length > 0 &&
activeFilters.length > 0 &&
! hasSetPhpFilterDefaults &&
! attributeTermsLoading
) {
setHasSetPhpFilterDefaults( true );
if ( ! blockAttributes.showFilterButton ) {
onSubmit( checked );
}
updateAttributeFilter(
productAttributesQuery,
setProductAttributesQuery,
attributeObject,
getSelectedTerms( activeFilters ),
blockAttributes.queryType === 'or' ? 'in' : 'and'
);
}
}
}, [
onSubmit,
productAttributesQuery,
setProductAttributesQuery,
attributeObject,
blockAttributes.queryType,
getSelectedTerms,
filteringForPhpTemplate,
checked,
hasSetPhpFilterDefaults,
attributeTermsLoading,
blockAttributes.showFilterButton,
] );

// Short-circuit if no attribute is selected.
Expand Down
4 changes: 4 additions & 0 deletions assets/js/utils/attributes-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export const removeAttributeFilterBySlug = (
* @param {Object} attribute An attribute object.
* @param {Array} attributeTerms Array of term objects.
* @param {string} operator Operator for the filter. Valid values: in, and.
*
* @return {Object} An attribute object.
*/
export const updateAttributeFilter = (
query = [],
Expand All @@ -79,4 +81,6 @@ export const updateAttributeFilter = (
} );
setQuery( sortBy( returnQuery, 'attribute' ) );
}

return returnQuery;
};