Is There a Path to Migrate Custom Dialog Contexts?

I am working on a proposal for migrating an application from Durandal to Aurelia.

One of the features we leveraged was the creation of custom dialog contexts. For reference I pulled this from Durandal’s documentation:

You an use the addContext API to add a new dialog context to the system. The context should have the following functions defined:

  • addHost(dialog) - In this function, you are expected to add a DOM element to the tree which will serve as the “host” for the dialog’s composed view. You must add a property called host to the dialog object which references the DOM element. It is this host which is passed to the composition module.
  • removeHost(dialog) - This function is expected to remove any DOM machinery associated with the specified dialog and do any other necessary cleanup.
  • compositionComplete(child, parent, context) - This function is called after the dialog is fully composed into the DOM, allowing your implementation to do any final modifications, such as positioning or animation. You can obtain the original dialog object via dialog.getDialog(context.model);.

This feature was very useful and we leveraged it to create dynamic elements like popovers, tooltips, peeks, notifications and resizable/draggable windows.

Here is a trimmed down example of a custom Dialog Context similar to what we used in our app:

import ko from "knockout";
import dialog from "plugins/dialog";

class PopoverHost{
  constructor(type) {
    // Set type to popover by default
    this.type = type || 'popover';
    this.isOpenCss = "dialog-is-opening--" + this.type;
    if (typeof dialog.getContext(this.type) === "undefined") {
      dialog.addContext(this.type, this);
    } else {
      console.log("Duplicate Warning: Cannot create dialog context: " + this.type + ". A dialog context of " + this.type + " already exists!");
    }
  }

  addHost(dialogInstance) {
    var $body = $('body');    
    var thisHost = $('<div class="ux-popover-host"></div>');

    $body.addClass(this.isOpenCss);
    thisHost.appendTo($body);
    dialogInstance.host = thisHost.get(0);
  }

  removeHost (dialogInstance) {
    dialogInstance.owner.destroy();
    ko.removeNode(dialogInstance.host);
  }

  compositionComplete(view, parent, model) {
    $('body').removeClass(this.isOpenCss);
  }

}

export default PopoverHost;

This code could then be used in this fashion:

// We create our dialog contexts in shell.js

import dialog from "plugins/dialog";
import PopoverHost from "viewModels/PopoverHost";    

//Create custom dialog host and and set the dialog type with PopoverHost constructor
let popoverHostInstance = new PopoverHost('tooltip');

// Then we can show and hide content with our custom context
//     (assuming viewModel and activationData are defined) 
dialog.show(viewModel, activationData, 'tooltip'); 
// **or**
dialog.showTooltip(viewModel, activationData)

After going through the Aurelia Dialog Plugin code I can see that it is a vastly different implementation then the strategy used by the Durandal Dialog. I can’t find a way to preserve our pattern of using custom Dialog contexts or any documentation that describes the best strategy to follow when upgrading this Durandal API feature to leverage Aurelia’s version of this plugin.

Where can I find more information about this topic?

*This post has been edited to improve the clarity of the question

You mean the view model that was used to create dialog will be discarded and all binding will be based on the context passed in activate ?

Uh, I am confused by the response. Going to edit my original question to clarify my problem.

The feature I am concerned about is documented well here: http://durandaljs.com/documentation/Showing-Message-Boxes-And-Modals.html

hi @gooeyideas,

I assume that this question is still relevant ;). To understand you correctly: You’re searching for a place to generate the “host” DOM element where your dialog is placed, right?

In “aurelia-dialog” this is done by the framework. By default the dialog is placed in an element which has the “body” tag as parent. You can change this behavior if you set the “host” property on dialog open:

this.dialogService.open({ viewModel: myViewModel, model: myData, host: placeParentElementHere });

The property is described here: Dialogs | Aurelia