Skip to content

JQuery.Deferred exception: Unable to process binding in magento 2.4.6

I am trying to add a form after shipping methods. But I am facing JQuery.Deferred exception When I remove knockout js code like if or foreach , the template is rendered but when I add if or foreach it gives error.

checkout_index_index.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
    <referenceBlock name="checkout.root">
        <arguments>
            <argument name="jsLayout" xsi:type="array">
                <item name="components" xsi:type="array">
                    <item name="checkout" xsi:type="array">
                        <item name="children" xsi:type="array">
                            <item name="steps" xsi:type="array">
                                <item name="children" xsi:type="array">
                                    <item name="shipping-step" xsi:type="array">
                                        <item name="children" xsi:type="array">
                                            <item name="shippingAddress" xsi:type="array">
                                                <item name="children" xsi:type="array">
                                                    <item name="shippingAdditional" xsi:type="array">
                                                        <item name="component" xsi:type="string">uiComponent</item>
                                                        <item name="displayArea" xsi:type="string">shippingAdditional</item>
                                                        <item name="children" xsi:type="array">
                                                            <item name="additional_block" xsi:type="array">
                                                                <item name="component" xsi:type="string">TLS_AwOnestepCheckoutExtended/js/view/student</item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </item>
            </argument>
        </arguments>
    </referenceBlock>
</body>
</page>

app/code/TLS/AwOnestepCheckoutExtended/view/frontend/web/js/view/student.js

define(
    [
        'jquery',
        'underscore',
        'ko',
        'uiComponent',
        // 'Aheadworks_OneStepCheckout/js/model/checkout-data',
        'Magento_Customer/js/model/customer',
        'Magento_Checkout/js/model/quote'
    ],
    function (
        $,
        _,
        ko,
        Component,
        customer,
        quote
    ) {
        'use strict';

       
        return Component.extend({
            defaults: {
                template: 'TLS_AwOnestepCheckoutExtended/student'
               
            },
            isCustomerLoggedIn: customer.isLoggedIn,
            isCourseForMe: true,
            hasCourses: false,
            customerData: customer.customerData,
            courses: [],

            /**
             * @inheritdoc
             */
            initialize: function () {
                var hasNewAddress;

                console.log('djjfjfjfj');

                this.hasCourses = Boolean(window.checkoutConfig.hasCourses);
                this.isCourseForMe = Boolean(1);
                this.customerData = customer.customerData;
                var coursesNewList = window.checkoutConfig.courses;

                coursesNewList.forEach(function (course){
                    course.is_forme = ko.observable(false);
                });

                this.courses = coursesNewList;

                console.log(this.courses);

                this._super();

                

                return this;
            },

            



            /**
             * On cancel button click event event handler
             */
           

            selectCourseForSomeOne: function(){
               // console.log(this);
                return 
            },

            selectCourseForMe:function(){
                //console.log(this);
            },
            onRenderComplete: function () {
                // call your script code
              $(".dobpicker").datepicker({
                      dateFormat:'dd/mm/yy',
                      changeMonth: true,
                      changeYear: true,
                      yearRange: "-80:", 
                      maxDate: "-10Y",
                      onChangeMonthYear: function(year, month, inst) {
                      var format = inst.settings.dateFormat;
                      var selectedDate = new Date(inst.selectedYear,inst.selectedMonth,inst.selectedDay);
                      var date = $.datepicker.formatDate(format, selectedDate);
                      $(this).datepicker("setDate", selectedDate);
                    }
                    });

               $("#customer-email").on('keyup change', function (e) {
                    $(this).val($(this).val().toLowerCase());
                     $(this).val($(this).val().replace(/s/g,''));
                  
                });

               setTimeout(function() { 
                 $("input[name='company']").parent().hide();
                    $('select[name="custom_attributes[buy_as_company]"]').change(function(e) {
                        if(this.value == 1){
                            $("input[name='company']").parent().show();
                        }
                        else{
                            $("input[name='company']").parent().hide();
                        }

                    });
                }, 3000);
            },
            onEmailDuplicateValidate: function (data,event) {
                
                const parent = event.currentTarget.parentNode;
                
                //console.log(event.currentTarget.name);
                var currentval = event.currentTarget.value
                var name = event.currentTarget.name
                var res =  event.currentTarget.id.split("-");
                var main_sku = data.productSKU;
               // console.log($(parent).find('input[name=students[0][is_forme]]').is(':checked'));
                //console.log($("input[name='students["+res[1]+"][is_forme]']").is(':checked'));
                var isforme = $("input[name='students["+res[1]+"][is_forme]']").is(':checked');
              //  alert(res[1]);
                $('.email_adress').each(function(i, obj) {
                    var res2 = obj.id.split("-");
                    var parent2 = obj.parentNode;
                    var sec_sku = $(this).data('productsku');
                  
                    var isforme2 = $("input[name='students["+res2[1]+"][is_forme]']").is(':checked');

                    if(currentval == obj.value && event.currentTarget.name != obj.name ){
                         //console.log(currentval+'----'+obj.value+'----'+event.currentTarget.name+'---'+obj.name);
                        if(isforme==true && isforme2 == true){
                          obj.style.color = "black";
                         $('#emailaddr-'+res[1]).css("color", "black");
                         $('#errr-'+res2[1]).css("display", "none");
                         $('#errr-'+res[1]).css("display", "none");
                            return;
                        }
                        if(main_sku != sec_sku){
                            return;
                        }
                        
                        obj.style.color = "red";
                       
                      //  $('#errr-'+res[1]).css("display", "block");
                        $('#errr-'+res2[1]).css("display", "block");

                        setTimeout(function(){
                     
                      $('#errr-'+res[1]).css("display", "block");
                       $('#emailaddr-'+res[1]).css("color", "red");
                     //  event.currentTarget.style.color = "red";
                      //  $('#errr-'+res2[1]).css("display", "block");
                    }, 1000);
                      
                    }
                    else{
                        obj.style.color = "black";
                      //  event.currentTarget.style.color = "black";
                       $('#emailaddr-'+res[1]).css("color", "black");
                         $('#errr-'+res[1]).css("display", "none");
                        $('#errr-'+res2[1]).css("display", "none");
                    }
                    
                });

                return true;
            },
            setIsForeMe:function(course, elem){
                let customerData = customer.customerData;

                var s_fname = $("[name='firstname']").val();
                var s_lname = $("[name='lastname']").val();
                var s_email = $("#customer-email").val();
                var s_phone = $("[name='telephone']").val();

                if (course.is_forme() === true)
                {
                    const parent = elem.currentTarget.parentNode;
                     setTimeout(function(){  
                     $(parent).find(".student-item-content > .email_adress").trigger('keyup');
                    }, 1000);
                    //console.log($(parent).find(".student-item-content > .email_adress"));
                }
                else
                {
                    const parent = elem.currentTarget.parentNode;
                    
                  var firstAddress;
                   for(var i in customerData.addresses){
                        firstAddress = customerData.addresses[i];
                        break;
                    }
                   

                  //  $(parent).find(".student-item-content > .email_adress").css("color", "black")
                  //  $(parent).find(".student-item-content > .msg-email").css("display", "none")
                    $(parent).find(".student-item-content > .first_name").val(customerData.firstname || s_fname);
                    $(parent).find(".student-item-content > .last_name").val(customerData.lastname || s_lname);
                    $(parent).find(".student-item-content > .email_adress").val(customerData.email || s_email);
                    
                    if (typeof  firstAddress !="undefined")
                    {
                    $(parent).find(".student-item-content > .phone_number").val(firstAddress.telephone);
                    }else{
                        $(parent).find(".student-item-content > .phone_number").val(s_phone);
                    }
                    if (typeof  customerData.dob !="undefined" && customerData.dob != '' && customerData.dob!=null){
                        var parts = customerData.dob.split('-');
                        var dmyDate = parts[2] + '/' + parts[1] + '/' + parts[0];
                        $(parent).find(".student-item-content > .c_dob").val(dmyDate);
                    }

                     setTimeout(function(){  
                     $(parent).find(".student-item-content > .email_adress").trigger('keyup');
                    }, 1000);
                   

                }

                course.is_forme(   !(course.is_forme()) );
                return true;

                // console.log(this);
            }
           
        });
    }
);

app/code/TLS/AwOnestepCheckoutExtended/view/frontend/web/template/student.html

<div class="testemail"></div>
<div class="aw-onestep-description">
    <div class="more-information">
        <span>Buying for yourselfss <b>?</b></span>
        <div class="mytooltip">
            If you are buying more than one course for yourself, then please tick the orange Boxes (This course is for me) and all the fields will automatically populate the booking forms.
        </div>
    </div>
    <div class="more-information-2">
        <span>Buying for a friend or colleague <b>?</b></span>
        <div class="mytooltip">
            If you are buying for more than one person, then add their details against the course that was purchased for them below in the booking form.
        </div>
    </div>
</div>
<!-- ko if: hasCourses -->
<div class="bookingform-title">
    <h2><span>COMPLETE BOOKING FORM</span></h2>
</div>
<div class="group-content student-fields">
    <!-- ko foreach: courses -->
    <div class="student-item">
        <div class="field choice is_forme" data-bind="click: $parent.setIsForeMe, attr: {id: $parent.domId(id)}">
            <input class="checkbox" data-bind="attr: {name: 'students[' + $index() + '][is_forme]', checked: $data.is_forme}" type="checkbox" value="1" >
            <label class="label">
                <span data-bind="i18n: 'This Course is for me.'">This Course is for me</span>
            </label>
        </div>
        <form id="onlyforvalidate" class="onlyforvalidate" onsubmit="event.preventDefault();">
            <div class="student-item-content">
                <!-- ko if: hasSessionData -->
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][productId]', value: $data.productId}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][productSKU]', value: $data.productSKU}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][session_type]', value: $data.session_type}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][spaces]', value: $data.spaces}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][start_at_date]', value: $data.start_at_date}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][start_at_time]', value: $data.start_at_time}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][end_at_date]', value: $data.end_at_date}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][end_at_time]', value: $data.end_at_time}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][course_id]', value: $data.course_id}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][course_session_id]', value: $data.course_session_id}" >
                <!-- /ko -->
                <h3 style="font-weight: bold;font-size: 16px;" data-bind="text: 'Candidate ' + (1 + $index())"></h3>
                <h3 style="font-size: 14px;margin-top: 8px;font-weight: bold;" data-bind="text: $data.name"></h3>
                <input type="hidden" data-bind="attr: {name: 'students[' + $index() + '][course]', value: $data.name}" >
                <input type="hidden" data-bind="attr: {name: 'students[' + $index() + '][productId]', value: $data.productId}" >
                <input type="hidden" data-bind="attr: {name: 'course_session[' + $index() + '][productSKU]', value: $data.productSKU}" >
                <input style="margin-bottom: 10px;" data-validate="{required:true}" type="text" required data-bind="attr: {name: 'students[' + $index() + '][first_name]'}" class="required first_name asteric" placeholder="First name" >
                <input style="margin-bottom: 10px;" type="text" required data-bind="attr: {name: 'students[' + $index() + '][last_name]'}" class="required last_name asteric" placeholder="Last name" >
                <input style="margin-bottom: 10px;" type="email" required data-bind="attr: {name: 'students[' + $index() + '][email]', 'data-productsku': $data.productSKU, id: 'emailaddr-' + $index() + ''}, event: {keyup: $parent.onEmailDuplicateValidate}" oninput="this.value = this.value.toLowerCase();this.value = this.value.replace(/s/g,'');" class="required email_adress asteric" placeholder="Email address" >
                <p class="msg-email" data-bind="attr: {id: 'errr-' + $index() + ''}" style="margin-top: -16px;padding-top: -1px;color: red;display: none;">Email address already added.</p>
                <input style="margin-bottom: 10px;" readonly type="text" data-bind="attr: {name: 'students[' + $index() + '][dob]'}, afterRender: $parent.onRenderComplete" placeholder="Date of Birth (dd/mm/yyyy)" class="dobpicker c_dob" >
                <input style="margin-bottom: 10px;" type="text" required data-bind="attr: {name: 'students[' + $index() + '][phone]'}" class="required phone_number asteric" placeholder="Mobile number" >
                <button type="submit" style="display: none;" class="chk_button">Check</button>
            </div>
        </form>
    </div>
    <!-- /ko -->
</div>
<!-- /ko -->

I am getting following error. Can anyone please help?

jQuery.Deferred exception: Unable to process binding "if: function(){return hasCourses }"
Message: Unable to process binding "foreach: function(){return courses }"
Message: Unable to process binding "attr: function(){return {id:$parent.domId(id)} }"
Message: id is not defined ReferenceError: Unable to process binding "if: function(){return hasCourses }"
Message: Unable to process binding "foreach: function(){return courses }"
Message: Unable to process binding "attr: function(){return {id:$parent.domId(id)} }"
Message: id is not defined
    at attr (eval at createBindingsStringEvaluator (https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:3221:28), <anonymous>:3:130)
    at evaluateValueAccessor (https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:3494:28)
    at https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:3671:44
    at update (https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:4429:59)
    at ko.dependentObservable.disposeWhenNodeIsRemoved (https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:3745:45)
    at Function.evaluateImmediate_CallReadThenEndDependencyDetection (https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:2331:115)
    at Function.evaluateImmediate_CallReadWithDependencyDetection (https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:2288:41)
    at Function.evaluateImmediate (https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:2253:40)
    at ko.computed.ko.dependentObservable (https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:2085:40)
    at https://tls.mage360.co.uk/static/frontend/JohnThomas/learningstation/en_GB/knockoutjs/knockout.js:3743:40 undefined