OroCommerce organize page view by loading subpart-subtree. any view is constructed by many blocks defined by block_id . when you make an event like add item to shopping or delete item from shopping list as result the layout system load and refresh some block related to this change for example for -add to shopping list - the layout load the main_menu_shopping_lists_wrapper which means the top shopping list toggle and all informations content (by adding the new items to content and chonging the items counts) .
let’s explain by complete example inside: src/Ibnab/Bundle/ImanBundle/Resources/views/layouts/iman/page/shopping_list_widget.html.twig
{% block _main_menu_shopping_lists_wrapper_widget %} {% set attr = layout_attr_defaults(attr, { 'data-page-component-module': 'oroshoppinglist/js/app/components/shoppinglist-widget-view-component', '~data-page-component-options': { view: 'oroui/js/app/views/layout-subtree-view', blockId: id, reloadEvents: ['shopping-list:refresh', 'frontend:shopping-list-item-quantity:update', 'frontend:item:delete'], }, 'data-dropdown-trigger': true, '~class': " main-menu__item main-menu__item--nested" }) %} <div {{ block('block_attributes') }}> {{ block_widget(block) }} </div> {% endblock %}
So we have here reloadEvents for some predefined actions like frontend:item:delete → reload full block with custom id on trigger by mediator frontend:item:delete → example of this trigger is in
vendor/oro/customer-portal/src/Oro/Bundle/FrontendBundle/Resources/public/js/app/components/delete-item-component.js
deleteWithoutRedirect: function(e) { mediator.execute('showMessage', 'success', this.successMessage, {flash: true}); mediator.trigger('frontend:item:delete', this.triggerData || e); }
when the customer delete item from shopping list mediator lunch event with trigger method which catched by reloadEvents .
The result url returned to refresh some part in the dom has all blocks which has reloadEvents like:
http://iman.com/index_dev.php?layout_block_ids%5B%5D=header_row_shopping_toggle&layout_block_ids%5B%5D=main_menu_shopping_lists_wrapper
or
http://iman.com/index_dev.php?layout_block_ids%5B%5D=main_menu_shopping_lists_wrapper&layout_block_ids%5B%5D=header_row_shopping_toggle&layout_block_ids%5B%5D=main_menu_shopping_lists_wrapper&layout_block_ids%5B%5D=shopping_list_view_container_content
you can see in url layout_block_ids%5B%5D=main_menu_shopping_lists_wrapper from our example
the component responsible to loading the subview is layout-subtree-manager.js in vendor/oro/platform/src/Oro/Bundle/UIBundle/Resources/public/js/layout-subtree-manager.js
they has many function addView , removeView , callViewMethod and last is reloadLayouts and more important and using ies
with
var eventBlockIds = this.reloadEvents[event] || []; return; }
the component generate all block layout_block_ids here for example for ‘frontend:item:delete’ all content blocks in bottom will get reloaded on event frontend:item:delete
main_menu_shopping_lists_wrapper & header_row_shopping_toggle & main_menu_shopping_lists_wrapper & shopping_list_view_container_content
Other thing you can call reloadEvents directly inside js component like:
mediator.trigger('layout-subtree:update:product', { layoutSubtreeUrl: routing.generate('oro_product_frontend_product_view', { id: productId, parentProductId: this.model.get('parentProduct'), ignoreProductVariant: true }), layoutSubtreeCallback: _.bind(this.afterProductChanged, this) });
and pass argument but the important is : layoutSubtreeUrl and layoutSubtreeCallback , which get used inside layout-subtree-manager.js like:
options = options || { layoutSubtreeUrl: null, layoutSubtreeCallback: null }; this._callViewMethod(eventBlockIds, 'beforeContentLoading'); $.ajax({ url: options.layoutSubtreeUrl || this.url, type: this.method, data: { layout_block_ids: eventBlockIds } }) .done(function(content) { self._callViewMethod(eventBlockIds, 'setContent', function(blockId) { return [content[blockId] || '']; }); self._callViewMethod(eventBlockIds, 'afterContentLoading'); if (options.layoutSubtreeCallback) { options.layoutSubtreeCallback(); } }) .fail(function(jqxhr) { self._callViewMethod(eventBlockIds, 'contentLoadingFail'); });
So you can call callViewMethod with 3 methods beforeContentLoading , setContent , afterContentLoading , contentLoadingFail
The result Response of subtree layout (block view part) generate inside LayoutListener by function :
protected function getLayoutResponse( ContextInterface $context, Request $request, LayoutManager $layoutManager ) { $blockIds = $request->get('layout_block_ids'); $response = []; foreach ($blockIds as $blockId) { if ($blockId) { $layout = $layoutManager->getLayout($context, $blockId); $response[$blockId] = $layout->render(); } } $response = new JsonResponse($response); } else { $layout = $layoutManager->getLayout($context); $response = new Response($layout->render()); } return $response; }
this is quick view.
Comments