Component Lifecycle
UI Component Lifecycle
1. initialize() → 2. initConfig() → 3. setDependencies()
4. initElement() → 5. onReady() → 6. destroy()
Lifecycle Methods
define([
'uiComponent'
], function(Component) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Module/component'
},
// Called during initialization
initialize: function() {
this._super();
console.log('Component initialized');
return this;
},
// Called when component is ready
onReady: function() {
console.log('Component ready');
},
// Called when component is destroyed
destroy: function() {
this._super();
console.log('Component destroyed');
}
});
});
Initialization Order
initialize: function() {
// 1. Parent initialization
this._super();
// 2. Set default values
this.setData(this.defaultData);
// 3. Initialize observables
this.initObservable();
// 4. Initialize modules
this.initModules();
return this;
}
Mixins
What are Mixins?
Mixins allow you to extend UI components without modifying the original code.
Creating a Mixin
// view/frontend/web/js/component-mixin.js
define([
'jquery'
], function($) {
'use strict';
return function(target) {
return target.extend({
// Override method
initialize: function() {
this._super();
console.log('Mixin initialized');
return this;
},
// Add new method
customMethod: function() {
return 'Custom behavior';
}
});
};
});
Register Mixin
// view/frontend/requirejs-config.js
var config = {
config: {
'mixins': {
'Vendor_Module/js/component': {
'Vendor_Module/js/component-mixin': true
}
}
}
};
Mixin with Configuration
define([], function() {
'use strict';
return function(target, config) {
return target.extend({
defaults: {
mixinConfig: config
},
initialize: function() {
this._super();
console.log('Mixin config:', this.mixinConfig);
return this;
}
});
};
});
Multiple Mixins
// Mixin 1
define([], function() {
return function(target) {
return target.extend({
method1: function() { return 'mixin1'; }
});
};
});
// Mixin 2
define([], function() {
return function(target) {
return target.extend({
method2: function() { return 'mixin2'; }
});
};
});
Both mixins are applied in order.
Extending Components
Extending via Inheritance
define([
'Vendor_Original/js/component'
], function(Component) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Extended/component'
},
// Override method
originalMethod: function() {
var result = this._super();
return result + ' extended';
},
// Add new method
newMethod: function() {
return 'New functionality';
}
});
});
Extending via Preferences (di.xml)
<config>
<type name="Vendor\Original\Component">
<plugin name="extend_component" type="Vendor\Extended\Plugin\ComponentPlugin"/>
</type>
</config>
Extending via Layout
<referenceBlock name="component.block">
<arguments>
<argument name="js_component" xsi:type="string">
Vendor_Extended/js/component
</argument>
</arguments>
</referenceBlock>
Composition Pattern
define([
'uiComponent',
'Vendor_Module/js/helper'
], function(Component, helper) {
'use strict';
return Component.extend({
defaults: {
modules: {
childComponent: '${ $.name }.child'
}
},
initialize: function() {
this._super();
helper.setupComponent(this);
return this;
}
});
});
Custom Component Creation
Custom UI Component
define([
'uiComponent',
'knockout'
], function(Component, ko) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Module/custom-component',
imports: {
data: '${ $.provider }:data'
},
exports: {
value: '${ $.provider }:value'
}
},
initialize: function() {
this._super();
this.value = ko.observable('');
return this;
},
getValue: function() {
return this.value();
},
setValue: function(val) {
this.value(val);
}
});
});
Component Configuration
<listing>
<settings>
<dataProvider class="Vendor\Module\Ui\DataProvider" name="dataProvider"/>
</settings>
<columns>
<column name="custom" class="Vendor\Module\Ui\Component\Column">
<settings>
<dataType>text</dataType>
<label translate="true">Custom Column</label>
</settings>
</column>
</columns>
</listing>
Data Providers
<?php
namespace Vendor\Module\Ui\DataProvider;
use Magento\Ui\DataProvider\AbstractDataProvider;
class DataProvider extends AbstractDataProvider
{
public function getData()
{
return [
'data' => [
'items' => $this->collection->getItems()
]
];
}
}
Component Events
initialize: function() {
this._super();
// Listen to provider changes
this.source.on('data.submitted', function(data) {
console.log('Data submitted:', data);
});
return this;
}
Quiz
1. What is a UI Component mixin?
2. Which method is called when a UI Component is ready?
3. How do you extend a UI Component via inheritance?
Flashcards
Question
What is the UI Component lifecycle?
Click to reveal answer
Answer
initialize → initConfig → initElement → onReady → destroy
Question
How do you create a mixin?
Click to reveal answer
Answer
Export function that takes target and returns target.extend()
Question
How do you extend a component?
Click to reveal answer
Answer
Component.extend({ ... })
Question
What is a data provider?
Click to reveal answer
Answer
PHP class that provides data to UI Components
Question
How do you register a mixin?
Click to reveal answer
Answer
In requirejs-config.js under config.mixins
Revision Notes
Key Takeaways
- 1. UI Components have a defined lifecycle with key methods
- 2. Mixins extend components without modifying originals
- 3. Components can be extended via inheritance or mixins
- 4. Data providers supply data to UI Components
- 5. Components use imports/exports for data flow
Interview Tips
- • Explain the UI Component lifecycle
- • Know when to use mixins vs inheritance
- • Discuss how to create custom UI Components
- • Be ready to extend an existing component
Cheat Sheet
Lifecycle: initialize → onReady → destroy
Mixin:
define([], function() {
return function(target) {
return target.extend({ ... });
};
});
Extend:
Component.extend({
defaults: { template: '...' },
initialize: function() { this._super(); }
});