Tag Archives: JavaScript

Control Add-ins Supercharged – Frameworks

In the last example I put online, we’ve noticed that it was difficult to achieve a good separation of concerns in the front end if we are building UI directly through DOM. Apart from the fact that it’s very inefficient, manipulating DOM directly makes it very difficult to structure your front-end logic. You quickly realize you need a framework for that.

And here I come to a big fat point I want to make once again, that I made in my session, too: don’t build a new framework; pick one off the shelf.

The thing is, in the JavaScript world there are ridiculously many frameworks. This article on Hackernoon is an introduction into this total insanity: https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f. There are memes, jokes, comics, websites, even Alexa skills that address the fact that people keep creating new JavaScript frameworks all the time. Guess what? A tiny fraction of them generate any traction at all, and only a few stick.

And don’t get me wrong – I am totally for improving things; “the room for improvement is the largest room in the world” they say. But I am not quite convinced that building a yet another framework will benefit the posterity all that much. If you want to improve on what we have, most of the leading frameworks are open-source, contribute away.

As with previous (and future) posts in this series, there is a GitHub repo + branch that accompanies this blog post, and you can find it here: https://github.com/vjekob/supercharged_01/tree/02-framework

(The featured image used under CC license from https://worldpece.org/content/how-standards-proliferate)


Now that you are done through this mouthful of the title, you may recognize that it’s the method you invoke when you want to run a control add-in trigger in AL from JavaScript.

There is nothing new about this method itself, it’s just that most people aren’t aware of full power of this method, and they are using this method in a very inefficient way. In this blog, I want to show you what this method can do for you that you may have not been aware of. And I hope I get you to change your habits.

The syntax is this:

It takes at minimum two arguments, and this is what most people invoke it. Obviously, name is the name of the event as declared in the controladdin object that you also must implement as a trigger inside the usercontrol in the page that uses it. Also, args is the array of arguments you want to pass to AL.

Imagine this is how you declare your event:

Then from JavaScript you would invoke it like this:

So far, very simple, obvious, and easy. But here we get to the biggest mistake most people do when invoking the Microsoft.Dynamics.NAV.InvokeExtensibilityMethod method. They invoke it directly. The reason why it’s a mistake is because most often you’ll want to synchronize the invocations between JavaScript and AL as much as you can, and this method – as anything in JavaScript that invokes stuff outside JavaScript – is asynchronous. If you have this:

… you will see the “You see me immediately” message before AL even gets a chance to start executing.

Yes, you can take advantage of more arguments here to make it behave differently. So, let’s take a look at the remaining two arguments.

The skipIfBusy argument tells the control add-in JavaScript runtime to not even invoke your event in AL if the NST session is currently busy doing something else. If you omit it, the skipIfBusy parameter defaults to false so it means your AL event will be raised, and if AL is already busy, it will be raised as soon as AL stops being busy.

The callback argument, though, is where cool stuff happens. This arguments is of function type (you can imply as much from its name), and it is invoked as soon as AL has finished doing whatever you just made it busy with. So, if you want some JavaScript code to happen after the SayHello event completes its work, you can do it like this:

However, that’s not really the most beautiful way of writing JavaScript. That’s how you would write it in late 1990’s, we are now nearly a quarter century ahead. Let’s write some at least tiny little bit less outdated JavaScript, and let’s introduce Promises. Promises are objects which allow you to synchronize asynchronous calls in a syntactically less offensive way than callbacks.

Let’s take a look at why promises are superior to callbacks.

Imagine you want to structure your code nicely, and you don’t want to just call your extensibility methods out of a blue, so you decide to wrap your call into a function, like this:

The syntax of the sayHello invocation is not really that easy to follow. However, we could translate the entire example to promises:

… and suddenly it becomes more readable. (Okay, a part of it being more readable is that I used arrow functions, but that’s because they are both supported at the same language level of JavaScript, and if your browser supports Promises, it will support arrow functions too, and if it doesn’t support Promises, it won’t support arrow functions either).

Apart from this readability benefit, there is another, far bigger benefit of wrapping your Microsoft.Dynamics.NAV.InvokeExtensibilityMethod invocations into promise-returning wrapper functions: it’s the fact that all promises are awaitable in JavaScript.

In newer versions of JavaScript (EcmaScript 2017 and newer) there is a concept of async functions. Async functions perform some asynchronous work, and you can await on them to make your code look and behave as if it were synchronous.

For example, if you have a function declared as this:

… then you can invoke it like this:

Cool thing about async/await is that it’s nothing more than syntactic sugar for Promises. Every async function implicitly returns a Promise, and you can invoke it either with await syntax, or with .then() syntax. Cosenquently, if a function explicitly returns a Promise, you can await on it as if it were declared as async.

In short, in our earlier example, we could easily do this:

… and it would have exactly the same meaning as the earlier example, except that this time it’s far more readable.

At this stage, our sayHello function is a handy asynchronous wrapper around Microsoft.Dynamics.NAV.InvokeExtensibilityMethod method invocation, but we can do better than that. Instead of having to write wrappers for every single event declared in your controladdin object, you could write something like this:

When you have that, you can use it like this:

Cool, isn’t it? You now not only never have to write that wordy Microsoft.Dynamics.NAV.InvokeExtensibilityMethod ever again (and risk making typos), you also have it fully synchronizable using the await syntax. But we can get even cooler – way cooler – than that. Hold my beer.

You know already that event invocations in AL are void, or that they cannot ever return a value. Your JavaScript cannot invoke AL and have AL return a value to it, that’s just not how AL/JavaScript integration works. At the heart it’s because it’s all asynchronous, but at the end of it, it’s just because Microsoft never cared enough to make it fully synchronized through an abstraction layer that could make it possible. Now that we’ve got it to an awaitable stage, let’s take it to another level by allowing AL to actually return values to your JavaScript wrappers.

Imagine that you declare this event in your controlladdin:

You pass a customer number to it, and you want it to return a JSON object containing your customer record information by its primary key. Ideally, you’ll want to invoke it like this:

Of course, that won’t work, because your GetCustomer trigger in AL – once you implement it in a page – cannot return values. You’d have to have a method declared in your controladdin object and then implement that method in the global scope in JavaScript, where you can pass the result of this operation, something you’d declare like this:

However, implementing it as a separate function in your JavaScript would require some acrobatics to allow you to retain your await getCustomer() syntax. But this is only true if you take the traditional approach of implementing methods as global-scope-level functions in one of your scripts. In JavaScript, you can implement methods on the fly, so let’s do it.

Let’s start with the statement that the GetCustomerResult function should be available in JavaScript only during the invocation of GetResult event in AL, and invoking it outside of such invocation would be a bug, and should not be allowed. When you do it like this, then you can write your code in such a way that you create this function in JavaScript just before you invoke the AL event, and you delete this function immediately when AL returns the result, something like this:

You can then do something like this:

How cool is this?

There is an even further level of awesomeness you can add to your event invocations, and it has to do with the skipIfBusy argument, but that’s a topic for a future blog post, I think you have enough to chew on for now. And I know that at this stage, invoking Microsoft.Dynamics.NAV.InvokeExtensibilityMethod directly, instead of through a pattern such as this, seems very stone age.

NAV TechDays 2018 Demos: Keyboard Shortcut Listener

The last of the NAV TechDays 2018 demo series comes with a little story.

While Waldo and I were preparing the “Evolution of the Titan” session, on Sunday before the conference, we were brainstorming the ideas of what would constitute a cool non-visual JavaScript demo. I wanted to showcase the things that JavaScript can do for you in control add-in context, but a less obvious thing. Everyone is expecting to see some cool visual demos, but I wanted to point out the vast possibilities in the non-visual area. Then Waldo asked me: can you make it run an action on a keypress, like post a document on F9?

And that was it! An amazingly cool demo that shows how you can do really cool stuff that falls beyond the visual realm.

Okay, I’ll calm down a bit. Keyboard shortcuts? Seriously? Well, unfortunately, yes. In NAV/BC web client (universal client included) there are almost no keyboard shortcuts. Microsoft is working on some improvements here, but the important thing, allowing developers to bind specific keyboard shortcuts to specific actions, is still conspicuously missing from NAV/BC.

So, I did this demo.

Continue reading NAV TechDays 2018 Demos: Keyboard Shortcut Listener

NAV TechDays 2018 Demos: User Profile Picture

One of the more effective, and probably completely unexpected, demos at Waldo’s and mine NAV TechDays 2018
session was the user profile picture demo. I say “completely unexpected” is that it shows something that you normally don’t expect from control add-ins. When hearing “control add-in”, most developers (but also most Microsoft people) have in mind a visual control that visualizes some data from NAV/BC and possibly allows you to interact with (C/)AL through that piece of UI. However, there are many other things possible, like having a completely non-visual “controls” that tap into the functionality of the web client and extend its functionality beyond what it was originally designed to do.

One of these is the user profile picture.

If you didn’t attend (or watch) the session, this is what the demo is about: it makes use of the user silhouette icon in the upper-right corner (that actually doesn’t represent anything, just sits there) and allows you to take your selfie and then uses that selfie as your profile picture that’s showing there instead. Pretty neat and cool..

How did I do it?

Continue reading NAV TechDays 2018 Demos: User Profile Picture

Extending the HTML trick: using actual images

Eric Sevareid famously said that the chief cause of problems is solutions. The same applies to the HTML trick I blogged about yesterday. As soon as you solve the problem of using HTML directly in your control add-ins, another problem arises: what do you do with actual images your control add-in includes?

This post explains how to solve that problem, and how to make it possible for your control add-in to both use HTML for defining UI and use relative control add-in paths to images.

Let’s dig in.

Continue reading Extending the HTML trick: using actual images