Customer Engagement & Dynamics CRM Forum

Expand all | Collapse all

Add callback to Javascript on a custom button

  • 1.  Add callback to Javascript on a custom button

    TOP CONTRIBUTOR
    Posted Apr 15, 2019 12:37 PM
    I have added a button via Ribbon Workbench that passes in selected items from a grid (Products) and will search my other database for those items. However, somewhere in my syntax, the callback must be incorrect because the window for the other database is opening too soon before the for loop has had an opportunity to complete and the query variable is blank at the time of the search. I have done some testing with console.log and it does not appear that the error is in the appending to the query string, but in the timing of the window.open.  How can I revise this so that the window opens only after the for loop is done?

    //Passes the selected items from the grid into the function
    function openAB(selectedIds,callback) {
    	//checks if there are any selected items and if not, will display alert
    	if (selectedIds != null && selectedIds != "") {
            //retrieves GUIDs and converts them to String, and then parses the array
    		var strIds = selectedIds.toString();
            var arrIds = strIds.split(",");
    		var query = ""
    		var url = "https://myurl.com/quickSearch?&keywords="
    		//for each GUID, retrieves attribute for product number and appends it to the query string seperated by a comma to be used in the search
    		for (var i = 0; i < arrIds.length; i++) {
    			var entityName = "product";
    			Xrm.WebApi.retrieveRecord(entityName, arrIds[i], "?$select=productnumber").then(function success(result) {
    				var id = result.productnumber;
    				query += id+",";
    				debugger;
    			}, 
    			function (error) {
    				Xrm.Utility.alertDialog("Error while retrieving the Product Record : " + error.message, null)
    			}
    			)
    		};
    		debugger;
    	}
    	else {
            alert("No records selected!");
    		}
    	callback(window.open(url+query))
    }


    ------------------------------
    Audrey Forrest
    Senior Accountant and Business Analyst
    Seattle WA
    CRMUG Co-Chapter Leader - Seattle
    D365 CRM V9, GP 2015 R2
    ------------------------------
    Conference-CRMUG_200x200


  • 2.  RE: Add callback to Javascript on a custom button

    MICROSOFT MVP
    Posted Apr 15, 2019 01:22 PM
    Audrey,

    Xrm.WebApi calls are executed in asyncway so your callback is executed before all the ids are collected. I would recommend to use Promise.all to collect all the results and call your callback after. Feel free to update thread if you experience any issue.

    ------------------------------
    Andrew Butenko
    ------------------------------

    Conference-CRMUG_200x200


  • 3.  RE: Add callback to Javascript on a custom button

    TOP CONTRIBUTOR
    Posted Apr 15, 2019 06:11 PM
    Thanks Andrew, I looked into Promise.all, and I couldn't figure out how to structure the promise with the loop to resolve it. It did however, give me a different idea. I changed the variable query from a string to an array, and then I inserted an if statement into the loop
    if (query.length == selectedIds.length) {
    window.open(url+query.toString())

    This may not be the most efficient way to code it, but it works!

    ------------------------------
    Audrey Forrest
    Senior Accountant and Business Analyst
    Seattle WA
    CRMUG Co-Chapter Leader - Seattle
    D365 CRM V9, GP 2015 R2
    ------------------------------

    Conference-CRMUG_200x200


  • 4.  RE: Add callback to Javascript on a custom button

    TOP CONTRIBUTOR
    Posted Apr 16, 2019 07:25 AM
    Edited by Rex Kenley Tan Apr 16, 2019 07:30 AM
    Audrey

    Why not use retrieveMultipleRecords? This will allow you make one call instead of multiple calls to server and you don't need Promise.all
    https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/clientapi/reference/xrm-webapi/retrievemultiplerecords

    As a general rule of thumb Promise.all is used for very different promises. It is inefficient to use it on very similar callbacks. But then again why use promises when you can use async/await?
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

    If I may,

    const openAB = async (selectedIds) => {
    if (!selectedIds) {
    return;
    }

    //assuming productid is the primary id field
    let oData = "?$select=productnumber&$filter=" +
    selectedIds.split(",").reduce((a,c) => {return `${a} or productid eq ${c}`}, "").trim().substring(3),
    result = await Xrm.WebApi.retrieveRecord("product", oData),
    query = "https://myurl.com/quickSearch?&keywords=" + result.reduce((a,c) => {return `${a}, ${c.productnumber}`.trim()}))

    window.open(query);
    }

    I wrote this off the top of my head but you get the general idea. Cheers!

    ------------------------------
    Rex Kenley Tan, MCP
    Tallmadge OH
    https://www.youracclaim.com/users/rex-kenley-tan

    *Always be CURRENT with JavaScript & C#, NEVER be obsolete.

    DISCLAIMER: All views expressed on this site are my own and DO NOT represent the opinions of ANY entity whatsoever with which I have been, am now, or will be affiliated.
    ------------------------------

    Conference-CRMUG_200x200


  • 5.  RE: Add callback to Javascript on a custom button

    MICROSOFT MVP
    Posted Apr 16, 2019 09:38 AM
    Rex, you have to be extremely careful about blindly recommending using features that aren't in browsers that CRM still supports.  I'm all up on using Async and Await, but either using TypeScript where it will transpile to that is IE friendly, or having the customer agree to not being able to use IE.

    ------------------------------
    Daryl LaBar
    President, MVP
    Gap Integrity
    Fishers IN
    ------------------------------

    Conference-CRMUG_200x200


  • 6.  RE: Add callback to Javascript on a custom button

    TOP CONTRIBUTOR
    Posted Apr 16, 2019 10:06 AM

    Daryl

    You can use async/await in IE using babel transpile and polyfill. You can do this without typescript.

    https://babeljs.io/docs/en/babel-preset-env

    https://medium.com/@zwacky/add-es7-async-await-support-into-your-non-bleeding-edge-build-process-ad0dded0d002

    Your browser would have to be PRETTY OLD for Babel not to support it.

    Babel can compile ES6 to work in IE9/IE10. Don't let fear of support hold you back. =) - Eric Elliott

    https://medium.com/@_ericelliott/babel-can-compile-es6-to-work-in-ie9-ie10-don-t-let-fear-of-support-hold-you-back-9f296e216df2

    Cheers!



    ------------------------------
    Rex Kenley Tan, MCP
    Tallmadge OH
    https://www.youracclaim.com/users/rex-kenley-tan

    *Always be CURRENT with JavaScript & C#, NEVER be obsolete.

    DISCLAIMER: All views expressed on this site are my own and DO NOT represent the opinions of ANY entity whatsoever with which I have been, am now, or will be affiliated.
    ------------------------------

    Conference-CRMUG_200x200


  • 7.  RE: Add callback to Javascript on a custom button

    MICROSOFT MVP
    Posted Apr 16, 2019 10:29 AM
    Edited by Daryl LaBar Apr 16, 2019 10:39 AM
    Yes there is quite a few different ways to make it "supported"  but IMHO, if you're not ready to give a clear explanation about how to setup and use the tools required to make your answer work, then you need to give a different answer.  For someone whose title is "Senior Accountant and Business Analyst", they most likely aren't ready to "make the leap" to a more regimented/enjoyable JS development world, and as such, giving them an answer that requires them to spend 2 days + learning the JS backstory/support framework to be fully compliant in order to make your code work, probably isn't the answer they are looking for, regardless of how "correct", or "better" it is.

    Don't get me wrong, I'm in 100% agreement on the technical point / correctness of your answer, I'd just suggest you be cognizant of your audience as you lend your skills and experience to the community.

    ------------------------------
    Daryl LaBar
    President, MVP
    Gap Integrity
    Fishers IN
    ------------------------------

    Conference-CRMUG_200x200


  • 8.  RE: Add callback to Javascript on a custom button

    TOP CONTRIBUTOR
    Posted Apr 16, 2019 11:06 AM
    Edited by Rex Kenley Tan Apr 16, 2019 11:21 AM

    Daryl

    They can always ask for clarification. :)

    I try not to assume what their learning style is or how much they know. I know some need a lot of hand holding while others just need a nibble and they run amok with it.

    A lot of people pm'ed me for clarification, so I have been doing it this way.

    https://www.crmug.com/communities/community-home/digestviewer/viewthread?MessageKey=893d2e5d-c12f-4d10-b6fd-122d8568d2cb

    I appreciate your input though, Cheers!

    Ps, Hmmm, maybe I can propose this as a course topic at summit. Crm365, Babel, WebPack.



    ------------------------------
    Rex Kenley Tan, MCP
    Tallmadge OH
    https://www.youracclaim.com/users/rex-kenley-tan

    *Always be CURRENT with JavaScript & C#, NEVER be obsolete.

    DISCLAIMER: All views expressed on this site are my own and DO NOT represent the opinions of ANY entity whatsoever with which I have been, am now, or will be affiliated.
    ------------------------------

    Conference-CRMUG_200x200


  • 9.  RE: Add callback to Javascript on a custom button

    SILVER CONTRIBUTOR
    Posted Apr 16, 2019 03:32 PM
    @Daryl LaBar you are both right, I don't think the majority of D365/Power Platform developers even know a good client-side workflow. I only got into it after working with an AngularJS team, where I had to make their Node style workflow fit my .NET style ALM system. This was a pain for lots of reasons but primarily that client side packages LOVE having hypens in the filenames, which D365 still doesn't support </rant>.

    @Rex Kenley Tan - I think turning your knowledge into a digestable talk as a course topic would be well welcomed by a lot of people. You really know your stuff :) To go over things like TypeScript, Polyfills, ES Versioning, Bundling etc. I, for one, would attend (probably virtually).

    ​​​​​​

    ------------------------------
    Ben Bartle
    IBM
    ------------------------------

    Conference-CRMUG_200x200


If you've found this thread useful, dive deeper into User Group community content by role