I am making a custom module before adding a product on cart with 3 options :
The upload option should display an upload form like :
My initial idea was to make two knockout components :
- Component to display options
- Component to show the download form
Each component should be independent just communicating with passed variables :
My first component looks like :
JS component to display options:
define([
'jquery',
'uiComponent',
'mage/validation',
'mage/url',
'mage/translate',
'ko',
], function ($, Component, validation, url, $t, ko, loadAction) {
'use strict';
var optionActive = ko.observable("");
return Component.extend({
defaults: {
template: 'Sebfie_Prescription/prescription'
},
options: {
},
initialize: function () {
this._super();
this.initButtons();
optionActive.subscribe(this.onOptionChange.bind(this));
},
initButtons: function() {
this.options.addToCartBtn = $("#product-addtocart-button");
this.options.nextBtn = $(".wizard-footer .btn-next");
this.disableAddButton();
this.options.nextBtn.click(function() {
$("#itoris_dynamicoptions_add_to_cart").click();
});
},
onOptionChange: function(value) {
if (value == "upload_prescription") {
this.onUploadPrescription();
}
if (value == "user_prescription") {
this.onUserPrescription();
}
if (value == "later_prescription") {
this.onLaterPrescription();
}
},
onLaterPrescription: function() {
this.enableAddButton();
},
onUserPrescription: function() {
this.disableAddButton();
},
onUploadPrescription: function() {
this.disableAddButton();
},
disableNextButton: function() {
this.options.nextBtn.addClass("disabled").attr("aria-disabled","true");
},
enableNextButton: function() {
this.options.nextBtn.removeClass("disabled").removeAttr("aria-disabled");
},
disableAddButton: function() {
this.options.addToCartBtn.addClass("disabled").attr("aria-disabled","true");
},
enableAddButton: function() {
this.options.addToCartBtn.removeClass("disabled").removeAttr("aria-disabled");
},
userImage: function() {
return window.prescription_images.use_previous;
},
uploadImage: function() {
return window.prescription_images.upload;
},
laterImage: function() {
return window.prescription_images.do_it_later;
},
setActive: function (value) {
optionActive(value);
},
getOptionActive: function() {
return optionActive();
},
getOptionActiveKo: function() {
return optionActive;
}
});
}
)
Template Sebfie_Prescription/prescription.html :
<div class="prescription-upload-wrapper">
<h3>PROVIDE YOUR PRESCRIPTION DETAILS</h3>
<input name="prescription_type" type="hidden" data-bind="attr: {value: getOptionActive()}"/>
<!-- ko if: getOptionActive() != 'upload_prescription' -->
<div class="row">
<div class="col-md-4">
<div class="choice" data-bind="click: setActive('user_prescription'), css: { active: getOptionActive() == 'user_prescription' }">
<div class="img">
<img data-bind="attr: { src: userImage() }" />
</div>
<div class="description">
<strong>Use a previous prescription</strong>
Please sign-in here
</div>
</div>
</div>
<div class="col-md-4">
<div class="choice" data-bind="click: setActive('upload_prescription'), css: { active: getOptionActive() == 'upload_prescription' }">
<div class="img">
<img data-bind="attr: { src: uploadImage() }" />
</div>
<div class="description">
<strong>Upload a prescription</strong>
Take a picture of your prescription of upload it into your portal by choosing this option.
</div>
</div>
</div>
<div class="col-md-4">
<div class="choice" data-bind="click: setActive('later_prescription'), css: { active: getOptionActive() == 'later_prescription' }">
<div class="img">
<img data-bind="attr: { src: laterImage() }" />
</div>
<div class="description">
<strong>DO IT LATER</strong>
You will receive an e-mail explaining how you can provide your prescription, after you have placed the order.
</div>
</div>
</div>
</div>
<!-- /ko -->
<!-- ko if: getOptionActive() == 'upload_prescription' -->
<div data-bind='scope: "prescriptionUpload", mageInit: {"prescriptionUpload": {option: getOptionActiveKo()}}'>
<!-- ko template: getTemplate() --><!-- /ko -->
</div>
<!-- /ko -->
</div>
Component Sebfie_Prescriotion/type/upload.html
define([
'jquery',
'uiComponent',
'mage/validation',
'mage/url',
'mage/translate',
'mage/template',
'ko',
], function ($, Component, validation, url, $t, template, ko, loadAction) {
'use strict';
var photoUrl = ko.observable();
return Component.extend({
defaults: {
template: 'Hellooptical_Prescription/type/upload',
select_option: null
},
initialize: function (params) {
this.select_option = params.option;
this._super();
},
fileUpload: function(data, e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onloadend = function (onloadend_e)
{
var result = reader.result; // Here is your base 64 encoded file. Do with it what you want.
photoUrl(result);
};
if(file)
{
reader.readAsDataURL(file);
}
},
photoUrl: function() {
return photoUrl();
}
});
}
)
Template type/upload.html
<input name="prescription_file" data-bind="event: {change: fileUpload}" type="file" accept="image/*" class="fileChooser"/>
<img class="myImage" data-bind="attr: {src: photoUrl() }"/>
But with this I got error :
Uncaught RangeError: Unable to process binding "template: function(){return getTemplate() }"
In fact the scope of :
<div data-bind='mageInit: {"prescriptionUpload": {option: getOptionActiveKo()}}'>
<!-- ko template: getTemplate() --><!-- /ko -->
</div>
Keeps to be the parent scope.