I say this as emphatically for the admin area as I do for the front end. But Magento has other ideas. I've been building a few admin interfaces recently, and I happened upon this catastrophic collision of old and broken code. It made me think about how sometimes good people write bad code, and we shouldn't judge them too harshly.
Are we sitting comfortably?
Good, then I'll begin.
I was creating a custom interface to allow orders to be placed in the back end of Magento to have a time slot selected. Similar to how you select a delivery hour when you buy groceries online. It was using Knockout, and I was feeling jolly proud of myself, but it only loaded on the second load. When you first visited the order creation screen, it wouldn't show up.
My colleague suggested that rather than the
sales_order_create_index layout handle, I might be better off with the
sales_order_create_load_block_data handle. I tried that, and was greeted with an altogether different problem.
On the first load, my delivery selection app would show up, but died with some syntax error. On the second load, it simply didn't show up. Perhaps the handles aren't equivalent, and perhaps I need both? After including both, I was back to a better situation: broken (but not missing entirely) on the first load, and correct on subsequent loads.
They say that one can measure progress in software development by marking movements from one error message to another, and sure enough, I was in a better situation.
The error was interesting, though. I had my standard JSON declaration of a JS component, something like this:
I knew that JSON could be funny about trailing commas and double quotes, but this worked on subsequent loads and should have been the same. Just in case, I copied the JSON inside the element and ran
pbpaste | jq . through my terminal. All was well.
A parser interprets the first opening brace as a new block, and then crumbles around the colon. Enclosing the above expression in parentheses (
)) will fix this problem.
Having a deeper look at the syntax error revealed that it was coming from an
eval(...) call inside
legacy-build.min.js. In Magento 2, this is the file that contains the Prototype library. (It's actually mapped. If you
It turns out that the order creation screen is actually a rather complicated multi-stage page that reloads itself and renders different things at different times depending on the state. So when we first visit that page by clicking the "Create Order" button on the order grid, we see a Customer selection grid. After selecting a Customer, we are invited to select a Website. After doing that, we go to the Order creation screen proper.
But it didn't reload the page! It used a little feature of Prototype called
Ajax.Updater. It performs an AJAX request and then updates the
innerHTML of some element with the response. As an added bonus, it also executes any inline scripts for you, because that won't just happen on its own. From the documentation:
If your HTML comes with inline scripts, they will be stripped by default. You'll have to pass true as the evalScripts option in order to see your scripts being executed.
The Magento core depends on this behaviour, and so it is enabled. To be fair, if it was disabled I'd be in an even worse situation. The problem is that the browser is smart enough to not execute inline
script tags when it doesn't recognise their
type attribute. Prototype, coming from before the dawn of time, apparently has no such understanding.
Nevertheless, now that I understood the problem, the solution was relatively straightforward: Just sell my soul to the devil and write it the way the rest of the admin area is written.
Ta-dah. A Bug's Life.