The Evolution of Modern Architecture: A Look at the Past and Future

  • Reading time:3 mins read

This is a single blog post layout by OceanWP.

You can completely change the layout (sidebar, no sidebar, edge to edge), control the position of the elements and their appearance with a user-friendly loop builder as well as style and customize all other aspects of your website.

Blog posts are the best tool to boost your online presence and SEO, so make it count by creating a presentable layout with a few simple clicks!

The best part? You are in full control over each and every post individually (change header style, menu, footer, top bar, or just about anything!) which enables you to make the best out of WordPress hassle-free.

Did we happen to mention you will get all of this for free? Get started with OceanWP today!

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

Vestibulum lacinia arcu

Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Morbi lacinia molestie dui. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi.

Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh.

Integer lacinia sollicitudin massa. Cras metus. Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante.

John Doe

Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh.

Continue ReadingThe Evolution of Modern Architecture: A Look at the Past and Future

AL Pragma Explorer – a new AL extension

  • Reading time:3 mins read

There is a cool new extension out there for AL developers that you should really check out: AL Pragma Explorer. The extension is almost as amazing as the work behind it, because even though this extension is published under my publisher name, it’s not really just mine. This was a team effort of my group at the BC TechDays 2022 preconference workshop, and I am so proud that we actually managed to pull this thing off.

So, here’s the story.

Continue ReadingAL Pragma Explorer – a new AL extension

Code annotations in AL – Please, don’t!

  • Reading time:10 mins read

One of good practices of writing C/AL Code for Microsoft Dynamics NAV since the dawn of civilization was annotating (commenting) code changes. If you are not sure what I mean by that, this is what I am talking about:

While standards varied about > vs +, or < vs -, or what the annotations should include, there was absolute consensus that annotating changes is an absolute must.

And it was a must. It was such an important rule that everyone followed it without questions asked. In my career, I’ve seen one or two situations of somebody changing or deleting a line of code without leaving any comment, and I’ve seen quite a lot of code, believe you me. It was that important.

It was that important in fact that it was one of the first things developers learned when they signed up for the job, and it was one of the rules they all followed from their first day.

Continue ReadingCode annotations in AL – Please, don’t!

Codeunit Interfaces – this time for real!

  • Reading time:1 min read

There is a particular programming language feature that I’ve always missed in AL (and C/AL for that matter): interfaces. I’ve dreamt about it, then blogged about it, then finally created a feature request in Microsoft’s AL GitHub repository. My GitHub feature request caught quite some traction and became the most upvoted feature request in less than a day.

Now, I don’t know if or to what extent it was my submission that influenced Microsoft, but it doesn’t really matter – what matters is that it’s becoming reality. Last week at NAV TechDays, Microsoft has presented an amazing new feature that will be coming to AL pretty soon: interface object type. And it’s official, or at least as official as Microsoft’s keynote is, and you can check Microsoft’s demo yourself at https://youtu.be/pl0LAvep6WE?t=4646

The feature is far more comprehensive than anyone could have hoped for, and it can be used for codeunits and enums, and in the future maybe even for a few more things. Who knows, or dares to dream. I dared, and I am pretty happy I did

Continue ReadingCodeunit Interfaces – this time for real!

Microsoft.Dynamics.NAV.InvokeExtensibilityMethod

  • Reading time:8 mins read

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:

Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(name, args[, skipIfBusy[, callback]]);

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:

event SayHello(FirstName: Text; LastName: Text);

Then from JavaScript you would invoke it like this:

Microsoft.Dynamics.NAV.InvokeExtensibilityMethod("SayHello", ["John", "Doe"]);

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:

Microsoft.Dynamics.NAV.InvokeExtensibilityMethod("SayHello", ["John", "Doe"]);
alert("You see me immediately");

… 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:

Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
  "SayHello",
  ["John", "Doe"],
  false,
  function() {
    alert("You see me after SayHello finished running in AL");
  });

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:

function sayHello(first, last, callback) {
   Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
     "SayHello", 
     [first, last],
     false,
     callback);
 }

 // Invoking the function
 sayHello("John", "Doe", function() {
   alert("You see me after SayHello finished running in AL");
 });

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

function sayHello(first, last) {
  return new Promise(resolve =>
    Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
      "SayHello", 
      [first, last],
      false,
      resolve));
}

// Invoking the function
sayHello("John", "Doe")
  .then(() => alert("You see me after SayHello finished running in AL"));

… 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:

async function somethingAsync() {
  // Do some asynchronous work
}

… then you can invoke it like this:

await somethingAsync();
alert("This won’t execute before somethingAsync completes its async work");

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:

function sayHello(first, last) {
  return new Promise(resolve =>
    Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
      "SayHello", 
      [first, last],
      false,
      resolve));
}

// Invoking the function
await sayHello("John", "Doe");
alert("You see me after SayHello finished running in AL");

… 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:

function getALEventHandler(eventName, skipIfBusy) {
  return (…args) => new Promise(resolve =>
    Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
      eventName,
      args,
      skipIfBusy,
      resolve));
}

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

// Obtain a reference to an asynchronous event invocation wrapper
var sayHello = getALEventHandler("SayHello", false);

// … and then use it as an asynchronous function
await sayHello("John", "Doe");
alert("You see me after SayHello finished running in AL");

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:

event GetCustomer(No: Code[10]);

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:

var cust = await getCustomer("10000");

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:

procedure GetCustomerResult(Cust: JsonObject);

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:

 function getALEventHandler(eventName, skipIfBusy) {
  return (...args) => new Promise(resolve => {
    var result;

    var eventResult = `${eventName}Result`;
    window[eventResult] = alresult => {
      result = alresult;
      delete window[eventResult];
    };

    Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
      eventName,
      args,
      skipIfBusy,
      () => resolve(result));
  });
}

You can then do something like this:

// Obtain a reference to an asynchronous event invocation wrapper
var getCustomer = getALEventHandler("GetCustomer", false);

// … and then use it as an asynchronous function
var cust = await getCustomer("10000");
alert(<code>Your customer record is ${JSON.stringify(cust)});

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.

Continue ReadingMicrosoft.Dynamics.NAV.InvokeExtensibilityMethod

Tips & Tricks: Going full screen with control add-ins in BC150

  • Reading time:2 mins read

Long time no see here, for I don’t know which time. That’s how it is these days, life kicks in, work kicks in, stuff kicks in, and then time flies and months go between posts here.

I am currently delivering my “Developing Control Add-ins using AL language” workshop at the first pre-conf day of NAV TechDays 2019, and while my group is busy developing their control add-in, I decided to answer the question I got five minutes ago: “can we please have this piece of code”?

So, here it goes. This little trick will allow you to go full screen with your control add-in in BC150. Having a full-screen control add-in is not something that you can do with just setting properties on your controladdin object, but it’s absolutely possible. Also, this is not something you can only do with BC150 – as a matter of fact you can do it in every single version of the Business Central or Dynamics NAV web client (or tablet, or phone client for that matter). However, every single client and every single version has a different overall HTML structure, so this particular trick applies to BC150. It may work on 140, it may work on 160 in the future, but it also may not.

The principle is the same, though: you hide unnecessary screen elements, and you make your control add-in iframe element full width and full height, and that’s it.

This is what your controladdin object must declare:

And then, this is what your control add-in initialization JavaScript code should do (typically you’d put this into your startup script):

function initialize() {
    function fill(frame) {
        if (!frame)
            return;
        frame.style.position = "fixed";
        frame.style.width = "100vw";
        frame.style.height = "100vh";
        frame.style.margin = "0";
        frame.style.border = "0";
        frame.style.padding = "0";
        frame.style.top = "0";
        frame.style.left = "0";
        frame.ownerDocument.querySelector("div.nav-bar-area-box").style.display = "none";
        frame.ownerDocument.querySelector("div.ms-nav-layout-head").style.display = "none";
    }
    
    window.top.document.getElementById("product-menu-bar").style.display = "none";
    fill(window.frameElement);
    fill(window.frameElement.ownerDocument && window.frameElement.ownerDocument.defaultView && window.frameElement.ownerDocument.defaultView.frameElement);
}

And that’s it.

Good luck full-screening!

Continue ReadingTips & Tricks: Going full screen with control add-ins in BC150

Codeunit interfaces in AL

  • Reading time:8 mins read

Nearly two and a half years ago I had a dream. It was about codeunit references and codeunit interfaces. And today, nearly two and a half years later I am still here, still having the same dream. We still cannot do codeunit interfaces in AL. But it doesn’t mean we don’t need them. We do. We badly do.

Two things triggered me to write this post about how badly we need codeunit interfaces, or any kind of polymorphism: a NAV TechDays talk, and a github project I saw.

Continue ReadingCodeunit interfaces in AL

Extending the HTML trick: using actual images

  • Reading time:3 mins read

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 ReadingExtending the HTML trick: using actual images

Encapsulation in JavaScript

  • Reading time:5 mins read

This will be my last post in the “JavaScript for (C/)AL Developers” series today. If I continued blogging about nearly pure JavaScript stuff, you could reasonably ask if this is in fact an NAV blog or a JavaScript one. It’s still NAV, and while the stuff I am about to write about is purely a JavaScript concept, I find it highly relevant for any control add-in developer. So, hold my beer, and bear with me for another one.

One of the complaints I often hear about JavaScript is that in JavaScript there is no encapsulation. This is almost completely true, except for the fact that it’s entirely false.

Where is the problem in the first place, and then what is the solution? Let’s dive in.

Continue ReadingEncapsulation in JavaScript

Some more thoughts about trampling over $

  • Reading time:1 min read

I am on a spree today. The number of topics I wanted to blog about has accumulated, and I just decided to dump the stuff over here while I both feel the motivation and have time for blogging. However, in this hurry, I forgot to add some important content to my previous post.

First, I forgot to mention that the example of my preserve-jquery script trick can be found in this github repo:

https://github.com/vjekob/controladdin-html

That’s the demo I blogged about earlier today, except this time it has two more branches:

  • Branch “problem”: showcases how a problematic script can break your code.
  • Branch “solution”: showcases how this problem can be fixed by applying the trick from my previous post

Also, there are two JSFiddles I created to follow screenshot-base examples from the post:

I have one more topic to cover today, which has much more to do with JavaScript than control add-ins, but I still find it very relevant. Stay tuned.

Continue ReadingSome more thoughts about trampling over $