Short Answer
Use the checkout_cart_save_before
event, this way it will serve the correct cart page as well as handling calculating the totals correctly.
Breakdown on why
The logic that decides what page you get served is in the following method Magento\Checkout\Block\Cart->getItemsCount()
which in turn calls getItemsCount
on the quote.
If the method returns a truthy value, you will get served the cart with the sidebar otherwise you get the one without.
The items_count
data property on the quote is only, with the exception of the dot mailer module, set when you collect totals for the quote in Magento\Quote\Model\Quote\TotalsCollector->_collectItemsQtys()
which is fired from the collect
method within the same class.
The order of execution for saving the cart is as follows: (removed unrelated bits for simplicity)
- Dispatch Event
checkout_cart_save_before
- Set Billing/Shipping Address
- Collect Totals (Here
items_count
is set)
- Dispatch Event
checkout_cart_save_after
So as you can see by using the checkout_cart_save_after
event, your code is fired after the totals are collected. Meaning the cart totals/items count is still set as the values before you removed the items.
And I believe (don't quote me on this) where the totals on the cart are loaded with ajax, this recalls the method to collect the totals. Which then causes the ajax'd totals to pull the correct items_count
and totals through. Although at this point its too late since the cart is already rendered.
Solutions
Ideally, if you want to modify the items in the quote you would use the before event checkout_cart_save_before
so when it calculates the shipping rates/totals if takes into account your changes.
Or you could recollect the totals after you've made your changes in the after event. $quote->setTotalsCollectedFlag(false)->collectTotals()
Or you can manually update the items_count
value on the quote after you remove an item from it like you are currently doing.