Accessing router in isolated scope


#1

I’m not sure if this question is more on the Aurelia side or the DevExpress side, but here goes: RE this example: https://github.com/PWKad/aurelia-devextreme-sample

I have the DevExpress component wrapped with an Aurelia customElement which works fine. I’m trying to navigate when the row is clicked. The dx component configuration lets you set a handler function for “onRowClick”. This also works, I get the data item in question. The issue is that this handler function is an isolated scope to the control, and I need to use this.router.navigateToRoute from the parent. I’m new to both Aurelia and DevExpress and I’m out of ideas on this. Using location.assign works, but it does a full page reload, so that’s not ideal.

If anyone can point me in a general direction I would appreciate the help. :slight_smile:


#2

I don’t really follow specifics because you linked a repo and I’m not sure where I’m looking in the repo.

One option would be to pass a .call binding in your customElement.

app.html

<my-component on-row-clicked.call="router.navigateToRoute('somewhere')"></my-component>

my-component-custom-element.js

@bindable onRowClicked;

attached() {
  configureTheComponent({
    rowClick: () => this.onRowClicked()
  });
}

Another, arguably better approach is to dispatch a custom event.

app.html

<my-component rowclicked.delegate="router.navigateToRoute('somewhere')"></my-component>

my-component-custom-element.js

attached() {
  configureTheComponent({
    rowClick: (all, the, data) => this.element.dispatchEvent(new CustomEvent('rowclicked', { 
      detail: { all, the, data } // you can use this to pass data upwards to your app view model
    });
  });
}

I wrote a short blog that might help you: http://davismj.me/blog/aurelia-drag-and-drop/


#3

Thank you! You got me thinking differently about it and I figured out how to accomplish what I needed. Instead of setting the DexExpress component config’s onRowClick to a method on the parent, I have it publishing an event using the EventAggregator.

So it now looks something like this (left out some details for simplicity):

@autoimport
export class Parent {
    router: Router;
    events: EventAggregator;
    onRowClickSub: Subscription;
    gridOptions: any = {}; // DevExpress.ui.dxDataGridOptions;
    
    constructor(router: Router, events: EventAggregator) {
        this.router = router;
        this.events = events;
        ...
        this.gridOptions.onRowClick = (event: any) => this.events.publish('onRowClick', { dxEvent: event, router: this.router });
        this.onRowClickSub = this.events.subscribe('onRowClick', this.handleOnRowClick);
    }

    ...

    handleOnRowClick(event: any) {
        if (!!event && !!event.dxEvent && !!event.dxEvent.data && !!event.router) {
            let id = event.dxEvent.data.thingId;
            event.router.navigate(`thing/${id}`);
        }
    }

    detached() {
        this.onRowClickSub.dispose();
    }
}

The template:

<template>
	<require from="../../../resources/custom-elements/dx-data-grid/dx-data-grid"></require>
	<dx-data-grid grid-options.bind="gridOptions"></dx-data-grid>
</template>