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

Commit

Permalink
Fix JS-rendered blocks inside Empty Cart
Browse files Browse the repository at this point in the history
  • Loading branch information
Aljullu committed Jul 22, 2020
1 parent f766fbf commit cd0553e
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 8 deletions.
2 changes: 1 addition & 1 deletion assets/js/base/utils/legacy-events.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const Event = window.Event || null;
* @param {boolean} bubbles Whether the event bubbles.
* @param {boolean} cancelable Whether the event is cancelable.
*/
const dispatchEvent = ( name, bubbles = false, cancelable = false ) => {
export const dispatchEvent = ( name, bubbles = false, cancelable = false ) => {
// In IE, Event is an object and can't be instantiated with `new Event()`.
if ( typeof Event === 'function' ) {
const event = new Event( name, {
Expand Down
37 changes: 36 additions & 1 deletion assets/js/base/utils/render-frontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
import { render } from 'react-dom';
import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundary';

// Some blocks take care of rendering their inner blocks automatically. For example,
// the empty cart. In those cases, we don't want to trigger the render functions of
// inner components on `DOMContentLoaded`. Instead, those wrapper blocks can trigger
// `wc-blocks_render_blocks_frontend` to render its inner blocks.
const selectorsToSkipOnDOMLoaded = [ '.wp-block-woocommerce-cart' ];

/**
* Renders a block component in the place of a specified set of selectors.
*
Expand All @@ -12,18 +18,32 @@ import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundar
* @param {string} props.selector CSS selector to match the elements to replace.
* @param {Function} [props.getProps ] Function to generate the props object for the block.
* @param {Function} [props.getErrorBoundaryProps] Function to generate the props object for the error boundary.
* @param {boolean} [props.renderOnDOMLoaded] Whether this function was triggered by a `DOMContentLoaded` event.
*/
export const renderFrontend = ( {
const renderBlockFrontend = ( {
Block,
selector,
getProps = () => {},
getErrorBoundaryProps = () => {},
renderOnDOMLoaded = false,
} ) => {
const containers = document.querySelectorAll( selector );

if ( containers.length ) {
// Use Array.forEach for IE11 compatibility.
Array.prototype.forEach.call( containers, ( el, i ) => {
if ( ! el.classList.contains( 'is-loading' ) ) {
return;
}
if ( renderOnDOMLoaded ) {
for ( let j = 0; j < selectorsToSkipOnDOMLoaded.length; j++ ) {
if (
el.parentNode.closest( selectorsToSkipOnDOMLoaded[ j ] )
) {
return;
}
}
}
const props = getProps( el, i );
const errorBoundaryProps = getErrorBoundaryProps( el, i );
const attributes = {
Expand All @@ -42,4 +62,19 @@ export const renderFrontend = ( {
}
};

/**
* Adds the event listeners necessary to render the block frontend.
*
* @param {Object} props Render props.
*/
export const renderFrontend = ( props ) => {
document.body.addEventListener( 'wc-blocks_render_blocks_frontend', () => {
renderBlockFrontend( props );
} );

document.addEventListener( 'DOMContentLoaded', () => {
renderBlockFrontend( { ...props, renderOnDOMLoaded: true } );
} );
};

export default renderFrontend;
14 changes: 12 additions & 2 deletions assets/js/blocks/cart-checkout/cart/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,24 @@ import {
ValidationContextProvider,
CartProvider,
} from '@woocommerce/base-context';
import { translateJQueryEventToNative } from '@woocommerce/base-utils';
import {
dispatchEvent,
translateJQueryEventToNative,
} from '@woocommerce/base-utils';
import withScrollToTop from '@woocommerce/base-hocs/with-scroll-to-top';

/**
* Internal dependencies
*/
import FullCart from './full-cart';

const EmptyCart = ( { content } ) => {
useEffect( () => {
dispatchEvent( 'wc-blocks_render_blocks_frontend' );
}, [] );
return <RawHTML>{ content }</RawHTML>;
};

const Block = ( { emptyCart, attributes, scrollToTop } ) => {
const { cartItems, cartIsLoading } = useStoreCart();

Expand Down Expand Up @@ -64,7 +74,7 @@ const Block = ( { emptyCart, attributes, scrollToTop } ) => {
return (
<>
{ ! cartIsLoading && cartItems.length === 0 ? (
<RawHTML>{ emptyCart }</RawHTML>
<EmptyCart content={ emptyCart } />
) : (
<LoadingMask showSpinner={ true } isLoading={ cartIsLoading }>
<ValidationContextProvider>
Expand Down
7 changes: 4 additions & 3 deletions assets/js/blocks/products/all-products/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n';
import { InnerBlocks } from '@wordpress/block-editor';
import { registerBlockType } from '@wordpress/blocks';
import { Icon, grid } from '@woocommerce/icons';
import classNames from 'classnames';
import '@woocommerce/atomic-blocks';

/**
Expand Down Expand Up @@ -63,9 +64,9 @@ const blockSettings = {
};
return (
<div
className={ getBlockClassName(
'wc-block-all-products',
attributes
className={ classNames(
'is-loading',
getBlockClassName( 'wc-block-all-products', attributes )
) }
{ ...data }
>
Expand Down
10 changes: 9 additions & 1 deletion assets/js/blocks/reviews/save.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import classNames from 'classnames';

/**
* Internal dependencies
*/
Expand Down Expand Up @@ -38,7 +43,10 @@ export default ( { attributes } ) => {

return (
<div
className={ getBlockClassName( className, attributes ) }
className={ classNames(
'is-loading',
getBlockClassName( className, attributes )
) }
{ ...data }
/>
);
Expand Down

0 comments on commit cd0553e

Please sign in to comment.