Question

UPDATE: You can access the viewmodels directly. If you need to trigger code to run after a render, use MutationObserver. I'll post my code as soon as I have a good working example.

Original Question: We have a lot of phone-in orders. I'm working on a module that auto populates the data in admin -> customer -> create new from our CRM solution using a webapi / jsonp call. This way, the data in magento does not create duplicates of data we already have stored in our 'master database'.

One task I still have left to do is add the customer's addresse(s). This seemed simple at first, until I realized how knockoutjs + magentojs is rendering everything on the customer form is blocking me from capturing templated elements. I'm having a heck of a time trying to capture the fieldsets (input elements) after after deleting all of the addresses programatically and creating new ones.

If you wonder why i'd do that, part of my code pops up a thing and goes "HEY, THIS PERSON EXISTS ALREADY. DO YOU WANT TO USE THEM?" and it removes anything you've already typed and replaces it with the correct info. Then the call center validates it, yadda yadda.

I'll share the code I have so far, but its not working quite right. FYI, this extends Abstract in order to catch the 'onUpdate' event. Don't rail me for attempting to access the collection inside of a collection item. I can't come up with a better way to catch the onUpdate event and still look at all the fields.

I also understand completely what is wrong, I just have no idea how to get around it. What is wrong is I assumed the elements generated by the .activate() call would be immediately available in the following

document.getElementsByClassName('admin__fieldset')

This is just wrong logic. Ideally, i'd LOVE to be able to pull the fieldset contents without having to resort to this UI trickery, then once i have everything set up, just render it out.

I'm not wanting to resort to jQuery hacks to watch for dom updates.

// jsonService variable is available here because it is in the php template render. see
// Stti/Customer/view/adminhtml/templates/javascriptinject.phtml

define(['ko','jquery','underscore','originalAbstract','uiElement', 'uiCollection'], function(ko, $, _, Abstract, Element, Collection) {
    "use strict";

    var theArray = {
        formFields: [],
        getKnockout: (function (ko) {
            return ko;
        })(ko),
        addressButton: null,
        populateFormFields: function () {
            this.formFields = [];

            // Populate the addressButton thinger
            this.addressButton = this.getNewAddressButton();

            var cb = (function(formFields){
                return function (data) {
                    cr(data, formFields);
                }
            })(this.formFields);

            var cr = function (data, formFields) {
                var elems = data.elems();
                for (var i = elems.length - 1; i >= 0; i--) {
                    if (elems[i].hasOwnProperty('uid')) {
                        formFields.push(elems[i]);
                    }
                }
            };

            var fieldsets = document.getElementsByClassName('admin__fieldset');
            for (var i = fieldsets.length - 1; i >= 0; i--) {
                var data = this.getKnockout.dataFor(fieldsets[i]);
                cb(data);
            }

        },
        cleanupAddresses: function () {
            // Remove all addresses
            var fieldsets = document.getElementsByClassName('admin__fieldset');
            for (var i = fieldsets.length - 1; i >= 0; i--) {
                var data = this.getKnockout.dataFor(fieldsets[i]);
                if (data.dataScope.indexOf('data.address') !== -1 && data.childType === 'group') {
                    data.destroy();
                }
            }
        },
        getNewAddressButton: (function () {
            var retVal = null;
            var customerItem = null;

            // Make sure the template is loaded

            var fieldsets = document.getElementsByClassName('admin__page-nav-item');
            for (var i = fieldsets.length - 1; i >= 0; i--) {
                var data = this.getKnockout.dataFor(fieldsets[i]);
                if (data.dataScope === 'data.address') {
                    data.activate();
                } else {
                    customerItem = data;
                }
            }

            // AT THIS POINT, I REALLY WANT KNOCKOUT TO RENDER.  
            fieldsets = document.getElementsByClassName('admin__fieldset');
            for (var i = fieldsets.length - 1; i >= 0; i--) {
                var data = this.getKnockout.dataFor(fieldsets[i]);
                var elems = data.elems();
                if (elems.length === 1 && data.dataScope === 'data.address' && data.index === 'address') {
                    retVal = elems[0];
                }
            }

            // Return the user to the Account Information section
            if (customerItem !== null) {
                //customerItem.activate();
            }

            return retVal;
        }),
        addNewAddress: function () {
            var retVal = null;

            // Use the addressButton to add a child address
            if (this.addressButton) {
                retVal = this.addressButton.addChild();
            }

            this.populateFormFields();

            return retVal;
        },
        onUpdate: function (newValue) {
            if (newValue) {
                this.clearAllFields();
                switch (this.index) {
                    case "email":
                        this.handleEmailBlur(newValue);
                        break;
                    case "constit_id":
                        this.handleConstitBlur(newValue);
                        break;
                }
            }
        },
        handleEmailBlur: function (newValue) {
            // Don't look up anything if the box was cleared out
            if (newValue != null || newValue != '') {
                this.clearAllFields();
                this.makeJsonReq("GetIndividualByEmail?emailaddress=" + newValue + '&callback=?');
            }
        },
        handleConstitBlur: function (newValue) {
            // Don't look up anything if the box was cleared out
            if (newValue != null || newValue != '') {
                this.clearAllFields();
                this.makeJsonReq("GetIndividualByConstit?constit=" + newValue + '&callback=?');
            }
        },
        jQueryByIndex: function (index) {
            function findUIDbyIndex(element) {
                return element.index === index;
            }

            return $('#' + this.formFields.find(findUIDbyIndex).uid);
        },
        makeJsonReq: function (callString) {
            var msg = null;

            $.getJSON(jsonService + callString, (function (localData) {
                    return function (data) {
                        doWork(data, localData);
                    }
                })(this)
            ).done(function () {
                console.log("Json Request Successful");
            }).fail(function () {
                console.log("Json Request Fail");
            }).always(function () {
                if (msg != "") {
                    alert(msg);
                }
            });


            function doWork(individual, localData) {

                // create as many addresses as the individual has
                if (individual != null) {
                    if (individual.NKIUserId != null) {
                        if (individual.NKIUserId != "") {
                            msg = "WARNING! Netforum reports this user has been added to magento with ID " + individual.NKIUserId + ". LOOKUP THE CUSTOMER FIRST AND CONFIRM YOU WANT TO ADD A NEW CUSTOMER!";
                        }
                        //window.location = "/admin";
                    }

                    if (individual.ConstitID != null) {
                        msg = localData.populateFields(individual, localData);
                    }
                    else {
                        msg = "Individual could not be found in NetForum. Verify that this IS a new customer.";
                    }
                }
                else {
                    msg = "Customer's email was not found in netforum. Be sure to use the correct constituent ID if this is an existing customer. A new Netforum customer will be created if it is blank or incorrect.";
                    // prepFormNoUser("constit");

                }
            }

        },
        populateFields: function (individual, localData) {
            // This function is used to get jquerySelector by index

            var getField = localData.jQueryByIndex;

            if (localData.jQueryByIndex('email')) {
                localData.jQueryByIndex('email').val = individual.PrimaryEmailAddress;
            }

            var addresses = null;
            var mageAddresses = [];

            if (individual.Addresses) {
                addresses = individual.Addresses;

                // Populate the form with the addresses
                for (var i = 0; i < addresses.length; i++) {
                    mageAddresses.push(localData.addNewAddress());
                }
debugger;
                var primaryAddress = null;
                for (var i=0; i < addresses.length; i++) {
                    addresses.each(function (e) {
                        try {
                            if (e.IsPrimary) {
                                primaryAddress = e;
                            }

                        } catch (err) {
                            // todo: handle errors
                        }

                        // Populate the billing address if we are on the order screen
                        if (primaryAddress.Id) {
                            if ($('order-billing_address_cxa_key')) {
                                $('order-billing_address_cxa_key').value = primaryAddress.Id;
                                $('order-billing_address_cxa_key').disable();
                            }
                        }
                        if (primaryAddress.Line1) {
                            if ($('order-billing_address_street0')) {
                                $('order-billing_address_street0').value = primaryAddress.Line1;
                            }
                        }
                        if (primaryAddress.City) {
                            if ($('order-billing_address_city')) {
                                $('order-billing_address_city').value = primaryAddress.City;
                            }
                        }
                        if (primaryAddress.Zip) {
                            if ($('order-billing_address_postcode')) {
                                $('order-billing_address_postcode').value = primaryAddress.Zip;
                            }
                        }
                        if (individual.PrimaryPhoneNumber) {
                            if ($('order-billing_address_telephone')) {
                                $('order-billing_address_telephone').value = individual.PrimaryPhoneNumber;
                            }
                        }

                    });
                }
            }

            if (individual.MemberType != null) {
                if ($('group_id')) {
                    var options = $$('select#group_id option');
                    if (individual.MemberType > 0) {
                        options[3].selected = true;
                        $('signup_method').value = "ADMIN-NEWORDER-EXISTING-MEMBER";
                    }
                    else {
                        options[0].selected = true;
                        $('signup_method').value = "ADMIN-NEWORDER-EXISTING-NONMEMBER";
                    }

                    $('signup_method').disable();

                }

                if ($('_accountconstit_id')) {
                    var options = $$('select#_accountgroup_id option');
                    if (individual.MemberType > 0) {
                        options[3].selected = true;
                        $('_accountsignup_method').value = "ADMIN-NEWCUSTOMER-EXISTING-MEMBER";

                    }
                    else {
                        options[0].selected = true;
                        $('_accountsignup_method').value = "ADMIN-NEWCUSTOMER-EXISTING-NONMEMBER";
                    }

                    $('_accountsignup_method').disable();
                }
            }

            if ($('_accountcst_key')) {
                $('_accountcst_key').value = individual.Id;
                $('_accountcst_key').disable();
            }
            if ($('cst_key')) {
                $('cst_key').value = individual.Id;
                $('cst_key').disable();
            }


            if (individual.FirstName) {
                if ($('_accountfirstname')) {
                    $('_accountfirstname').value = individual.FirstName;
                }
                if ($('order-billing_address_firstname')) {
                    $('order-billing_address_firstname').value = individual.FirstName;
                }
            }
            if (individual.LastName) {
                if ($('_accountlastname')) {
                    $('_accountlastname').value = individual.LastName;
                }
                if ($('order-billing_address_lastname')) {
                    $('order-billing_address_lastname').value = individual.LastName;
                }
            }
            if (individual.MiddleName) {
                if ($('_accountmiddlename')) {
                    $('_accountmiddlename').value = individual.MiddleName;
                }
                if ($('order-billing_address_middlename')) {
                    $('order-billing_address_middlename').value = individual.MiddleName;
                }
            }

            if (individual.DateOfBirth) {
                var dob = new Date(parseInt(individual.DateOfBirth.substr(6)));
                var fDob = dob.toString('MM-dd-yyyy');
                if ($('_accountdob')) {
                    $('_accountdob').value = fDob;
                }
            }

            return msg;
        },
        clearAllFields: function () {
            var inputs = $(':input');
            for (var i = 0; i < inputs.length; i++) {
                inputs[i].value = '';
            }

            this.cleanupAddresses();
            this.populateFormFields();
        }
    };

    // Use jQuery to figure out what page we are on.  the body will contain the class matched by name in the
    // view/adminhtml/layout folder
    if ($('body.customer-index-edit').length > 0) {
        return Abstract.extend(theArray);
    }

});
Was it helpful?

Solution

You can use the afterRender custom binding provided by the Magento core.

Here is an example from the core. The template adds afterRender="setStickyNode" which calls the setStickyNode function on the ViewModel.

Here is another basic example:

My template:

<div afterRender="doSomething" id="example1">
    <h1>This is a test</h1>
</div>

My ViewModel:

return {
    doSomething: function () {
        // Code that will run after id="example1" element is rendered on the page.
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top