3

I am making a custom module before adding a product on cart with 3 options :

enter image description here

The upload option should display an upload form like :

enter image description here

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.

1 Answer 1

0

change your code like this.

define([
  'jquery',
  'uiComponent',
  'mage/validation',
  'mage/url',
  'mage/translate',
  'mage/template',
  'ko',
  ], function ($, Component, validation, url, $t, template, ko) {
      '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();
          }
      });
  }
)
5
  • What have you changed? Copying and pasting doesn't help anybody learn.
    – Ben Crook
    Commented Oct 9, 2018 at 13:54
  • I remove addition parameter called "loadAction". Kindly check the code. Commented Oct 9, 2018 at 13:56
  • after making above change, run caching, upgrade and deploy command and then check. Commented Oct 9, 2018 at 13:56
  • Changing nothing, the error was not here. It's an issue about scope.
    – Sebastien
    Commented Oct 9, 2018 at 15:35
  • @DhirenVasoya A better idea?
    – Sebastien
    Commented Oct 10, 2018 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.