Table of Contents for
Magento 2 Development Quick Start Guide

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Magento 2 Development Quick Start Guide by Branko Ajzele Published by Packt Publishing, 2018
  1. Magento 2 Development Quick Start Guide
  2. Title Page
  3. Copyright and Credits
  4. Magento 2 Development Quick Start Guide
  5. Packt Upsell
  6. Why subscribe?
  7. Packt.com
  8. Contributors
  9. About the author
  10. About the reviewer
  11. Packt is searching for authors like you
  12. Table of Contents
  13. Preface
  14. Who this book is for
  15. What this book covers
  16. To get the most out of this book
  17. Download the example code files
  18. Code in Action
  19. Conventions used
  20. Get in touch
  21. Reviews
  22. Understanding the Magento Architecture
  23. Technical requirements
  24. Installing Magento
  25. Modes
  26. Areas
  27. Request flow processing
  28. Modules
  29. Creating the minimal module
  30. Cache
  31. Dependency injection
  32. Argument injection
  33. Virtual types
  34. Proxies
  35. Factories
  36. Plugins
  37. The before plugin
  38. The around plugin
  39. The after plugin
  40. Events and observers
  41. Console commands
  42. Cron jobs
  43. Summary
  44. Working with Entities
  45. Technical requirements
  46. Understanding types of models
  47. Creating a simple model
  48. Methods worth memorizing
  49. Working with setup scripts
  50. The InstallSchema script
  51. The UpgradeSchema script
  52. The Recurring script
  53. The InstallData script
  54. The UpgradeData script
  55. The RecurringData script
  56. Extending entities
  57. Creating extension attributes
  58. Summary
  59. Understanding Web APIs
  60. Technical requirements
  61. Types of users
  62. Types of authentication
  63. Types of APIs
  64. Using existing web APIs
  65. Creating custom web APIs
  66. Understanding search criteria
  67. Summary
  68. Building and Distributing Extensions
  69. Technical requirements
  70. Building a shipping extension
  71. Distributing via GitHub
  72. Distributing via Packagist
  73. Summary
  74. Developing for Admin
  75. Technical requirements
  76. Using the listing component
  77. Using the form component
  78. Summary
  79. Developing for Storefront
  80. Technical requirements
  81. Setting up the playground
  82. Calling and initializing JS components
  83. Meet RequireJS
  84. Replacing jQuery widget components
  85. Extending jQuery widget components
  86. Creating jQuery widgets components
  87. Creating UI/KnockoutJS components
  88. Extending UI/KnockoutJS components
  89. Summary
  90. Customizing Catalog Behavior
  91. Technical requirements
  92. Creating the size guide
  93. Creating the same day delivery
  94. Flagging new products
  95. Summary
  96. Customizing Checkout Experiences
  97. Technical requirements
  98. Passing data to the checkout
  99. Adding order notes to the checkout
  100. Summary
  101. Customizing Customer Interactions
  102. Technical requirements
  103. Understanding the section mechanism
  104. Adding contact preferences to customer accounts
  105. Adding contact preferences to the checkout
  106. Summary
  107. Other Books You May Enjoy
  108. Leave a review - let other readers know what you think

Calling and initializing JS components

Calling and initializing JS components might seem a bit challenging at first. There are two types of syntax notations used with Magento JS components:

  • Declarative:
    • Using the data-mage-init attribute
    • Using the <script type="text/x-magento-init" /> tag
  • Imperative:
    • Using the <script> tag, without the type="text/x-magento-init" attribute

To better understand the data-mage-init notation, let's take a look at a partial <PROJECT_DIR>/lib/web/mage/redirect-url.js file extract:

define([
'jquery',
'jquery/ui'
], function ($) {
'use strict';
$.widget('mage.redirectUrl', {
options: {
event: 'click',
url: undefined
},
_bind: function () { /* ... */ },
_create: function () { /* ... */ },
_onEvent: function () { /* ... */ }
});
return $.mage.redirectUrl;
});

This here is a jQuery widget wrapped as an AMD module; more on that later on. data-mage-init knows how to interpret mage.redirectUrl as a redirectUrl component. By studying the redirectUrl widget code, we can see it can be used not only with the button and the link type of elements but with the select type as well. Let's go ahead and append our playground.phtml file with the following:

<a data-mage-init='{"redirectUrl":{"url":"http://test.url"}}'>
<span><?= __('Test') ?></span>
</a>

<button type="button"
data-mage-init='{"redirectUrl":{"url":"http://test.url"}}'>
<span><?= __('Test') ?></span>
</button>

<select data-mage-init='{"redirectUrl": {"event":"change"}}'>
<option value="http://test.url/1">Test#1</option>
<option value="http://test.url/2">Test#2</option>
<option value="http://test.url/3">Test#3</option>
</select>

While the click event works perfectly for link and button elements, the select element relies on a more specific change event. Therefore, our select element exploits the fact that the redirectUrl component accepts the event configuration option. This makes for a nice and clean little example of reusing a single component multiple time.

To better understand the <script type="text/x-magento-init" /> notation, let's take a look at a partial <MAGENTO_DIR>/module-cookie/view/frontend/web/js/notices.js file extract:

define([
'jquery',
'jquery/ui',
'mage/cookies'
], function ($) {
'use strict';
$.widget('mage.cookieNotices', {
_create: function () {
//...
}
});
return $.mage.cookieNotices;
});

Just like in our first example, this is just another jQuery widget essentially. What the cookieNotices widget does is take the given content and display it as cookie notice alert to the user, doing so until the user finally hits the Allow Cookies button. We can easily reuse this widget to inject our own content. While both cookieNotices and redirectUrl are jQuery widgets, the way they are used in Magento differs.

Let's go ahead and append our playground.phtml file with the following HTML bits:

<div id="playgroundCookieBlock" class="message global cookie"
style="display: none;">
<p>
<strong><?= $block->escapeHtml(__('We use cookies to make your experience better.')) ?></strong>
<span><?= $block->escapeHtml(__('To comply with the new e-Privacy directive, we need to ask for your consent to set the cookies.')) ?></span>
<?= $block->escapeHtml(__('<a href="%1">Learn more</a>.', 'http://magelicious.loc/privacy'), ['a']) ?>
</p>
<div class="actions">
<button id="btn-cookie-allow" class="action allow primary">
<span><?= $block->escapeHtml(__('Allow Cookies')) ?></span>
</button>
</div>
</div>

This is to simulate our intent for a custom cookie widget, with special content and a cookie name. Let's further append the playground.phtml file with a declarative call to cookieNotices JS component:

<script type="text/x-magento-init">
{
"#playgroundCookieBlock": {
"cookieNotices": {
"cookieAllowButtonSelector": "#btn-cookie-allow",
"cookieName": "playgroundCookie",
"cookieValue": "playgroundCookieValue",
"cookieLifetime": "300",
"noCookiesUrl": "http://magelicious.loc/no-cookies"
}
}
}
</script>

Unlike the redirectUrl widget, which had a nice list of options defined at the very start of the widget definition, the cookieNotices widget does not have those. It merely references those options throughout the code, via this.options.<optionPushedViaMagentoInit> calls. This is really a default jQuery widget options object. The reason we are bringing it up is merely to understand how, most of the time, one needs to take a more involved approach toward inspecting existing JavaScript components code, instead of just focusing on the set of possible default options.

To better understand the <script> tag notation, let's take a look at a partial <MAGENTO_DIR>/module-ui/view/base/web/js/modal/modal.js file extract:

define([
/* ... */
], function ( /* ... */ ) {
'use strict';
//...
$.widget('mage.modal', {
//...
});
return $.mage.modal;
});

As in the previous two examples, this again is just a jQuery widget. Now let's go ahead and append our playground.phtml file with the following HTML bits:

<div>
<a href="#" id="playgroundModalLink">Show modal!</a>
</div>

<div id="playgroundModal">
<p>Content...</p>
</div>

This is to simulate our intent of creating a modal box, with special content. Now, let's use the modal widget to turn this into an actual modal. We further append our playground.phtml file, as follows:

<script>
require([
'jquery',
'mage/translate',
'Magento_Ui/js/modal/modal'
], function ($, $t, modal) {
var options = {
title: 'Playground Modal',
buttons: [{
text: $t('Continue'),
click: function () {
this.closeModal();
}
}]
};

modal(options, $('#playgroundModal'));

$('#playgroundModalLink').on('click', function () {
$('#playgroundModal').modal('openModal');
});
}
);
</script>

This time we are using the <script> tag approach to utilize the JS component.

To ensure our code evaluates on page load, we can further wrap our modal widget related code into a function, as follows:

<script>
require([
/* libraries ... */
], function ( /* params ... */ ) {
$(function () {
// Raw JS code...
});
}
);
</script>

Likewise, we can use a RequireJS domReady module to execute our JS code on DOM:

<script>
require([
'jquery',
'mage/translate',
'domReady!'
], function ($, $t) {
// Raw JS code...
});
</script>

The ! character used in domReady! is a syntax reserved for plugins. While there is more to it, suffice to say that in a case of domReady! the plugin exists simply as a way of waiting until DOM gets loaded before invoking our function.

The choice of calling and initializing JS components depends on how they are written and how they are intended to be used. We use the declarative notation when our component requires initialization. The configuration is prepared on the backend and simply outputted to the page. We use the imperative notation on the pages that use raw JS code; this allows us to execute particular business logic.