Au 2.0RC: Problems with the new Enhance API where enhanced markup doesn't have access to the view-model where it is defined (worked in Au 1.0)

Hello,

DevExtreme widgets and the new Enhance API are working well together. But of all the scenarios I tested after having implemented my new bridge between Aurelia 2.0 and DevExtreme, and incorporating all of the knowledge I acquired on this forum, I did not test this one (apparently):

bid-jobsites-list.html (NOT WORKING)

<div class="tsi-list-layout">
   ...
   <tsi-dx-popup
     visible.two-way="showDescription"
     content-template="description"
     container=".tsi-list-layout"
   >
     <dx-template name="description">
       <my-description description.bind="someText"></my-description>
     </dx-template>
   </tsi-dx-popup>
   ...
</div>

where someText is on the view model associated with bid-jobsites-list.html. After the template is enhanced and ingested into the DevExtreme widget, it loses its context with respect to the view-model associated with the owning view (where it is defined). It cannot find someText.

A number of DevExtreme widgets do not pass in data to some of their templates. In that case, the widget has noModel set to true by the widget internally. Most of the widgets do pass in data, and I hand this off to enhance in the familiar way:

...
onResolve(
   Aurelia.enhance({
     container: config.container,
     host: $template,
     component: {
       data: renderData.model,
     },
   }),
   (enhancedView) => { ... }
...

All works well. But components like Popup, Popover, Tooltip, etc. have content templates where no data is passed in. Apparently, it is expected that the data will come from the template’s context, not from the widget.

Compared to Aurelia 1.0

This was no problem in Aurelia 1.0. Consider the following from one of my components in Aurelia 1.0:

tsi-model-editor-command-bar.html (WORKING)

...
<tsi-dx-popup visible.bind="confirmClose">
   <dx-template name="content">
      <div class="tsi-dialog__text">${text.areYouSure}</div>
      <div class="tsi-dialog__text">${text.closingWithoutSaving}</div>
      <div class="tsi-dialog__buttons-wrapper">
         <div class="tsi-dialog__buttons">
            <tsi-dx-button styling-mode="text" text.bind="text.keepEditing"
                  click.delegate="onCancelClose()">
            </tsi-dx-button>
            <tsi-dx-button type="default" text.bind="text.closeAnyways"
               click.delegate="onConfirmClose()">
            </tsi-dx-button>
         </div>
      </div>      
   </dx-template>
</tsi-dx-popup>
...

If you take a look in the dx-template markup above, you’ll see a reference to text.* in some of the bindings. That’s a field defined on the view-model. You can also see a number of delegate bindings. Their handlers are also on the view-model.

Context was preserved in Aurelia 1.0 and the text bindings and delegate bindings worked even after the enhanced template was ingested.

What’s going on here? Why are the dx-templates not seeing the view-model where they’re defined?

Maybe can you help with a simple repro? Itll be easier both ways: understanding and explaining the issues.

Hello @bigopon ,

Thank you for getting back to me.

I’ll need a bit of time to put the repro together. I have to figure out how much of the codebase to bring in to get to a minimum repro.

I’ll work on that tomorrow.

Hello @bigopon ,

I have posted a repro at…

I would draw your attention to welcome-page.html, at the bottom. I have a dx-template that I’ve defined as the popup’s content template. You’ll notice that I reference the view-model with this line:

<div>${description}</div>

But the description doesn’t show in the popup. This worked just fine in Aurelia 1.0, even after the template was ingested into the DevExtreme widget.

The DI container is configured in tsi-dx-widget-base.js:

this.scopedDiContainer = this.diContainer.controller.container.createChild({
      inheritParentResources: true,
});

All of my view-only wrappers inherit from this base class.

And the enhancement is defined in TsiDxAuTemplateBridgeService.js:

createRenderer(rawTemplate, renderData, config) {
    const $template = rawTemplate.cloneNode(true);
    renderData.container.append($template);

    onResolve(
      Aurelia.enhance({
        container: config.container,  // <-- The scoped container from tsi-dx-widget-base.js is supplied here
        host: $template,
        component: {
          data: renderData.model,
          contentData: this.contentData,
        },
      }),
      (enhancedView) => {
        dxEventOn($template, 'dxremove', () => {
          if (!enhancedView) {
            return;
          }

          onResolve(enhancedView.deactivate(enhancedView, config.controller), () => {
            enhancedView.dispose();
          });
        });

        return $template;
      },
    );
  }