Ben Kilah
Ben Kilah

Reputation: 3475

Aurelia DataTables Recompile

I've been exploring Aurelia and so far have loved what I've seen. I've come accross an issue that I'm not really sure how to solve. I used jquery datatables for large results in my current app with angular, using server side fetches. Datatables has a function you can call whenever a new row is added to the table (fnRowCallback - http://legacy.datatables.net/ref#fnRowCallback, or "createdRow" - https://datatables.net/examples/advanced_init/row_callback.html#) - This is really handy as you can recompile the dom after each row (costly I know).

This enables you to reference functions that exist in the current scope (or viewModel) that the datatable exists in. For example:

In my view model:

export class DataTableTest{

  test(){
   alert('this is a test');
 }

}

In the return results from a datatable fetch:

{name:'blah',age:40,actions:"<a click.delegate='test();'>Test</a>"}

For some reason I can't seem to figure out how to recompile an element once it has been added to the dom.

Does anyone have any ideas how you could do this?

UPDATE: These are the original options I pass to datatables:

    var options = {
        "fnRowCallback": function (nRow) {
            $compile($(nRow).contents())(scope);
        }
    };

I've tried the following after injecting that compiler service:

        "fnRowCallback": function (nRow) {
               this.compiler.compile($(nRow).contents()).fragment.innerHTML;
        },

But I always get Uncaught TypeError: Cannot read property 'compile' of undefined - I do this in the "attached" function.. If I console.log(this.compiler) outside of these options, it's available. Also, we don't need to return html back to datatables, just run the compile on the contents. Many thanks for all your help!

Upvotes: 3

Views: 848

Answers (1)

Charleh
Charleh

Reputation: 14012

You can use a compiler service to compile the element:

import {inject, ViewCompiler, ViewResources, Container} from 'aurelia-framework';

/**
 * Compiler service
 *
 * compiles an HTML element with aurelia
 */
@inject(ViewCompiler, ViewResources, Container)
export class Compiler {

    viewCompiler: any;
    resources: any;
    container: any;

    constructor(viewCompiler, resources, container) {
        this.viewCompiler = viewCompiler;
        this.resources = resources;
        this.container = container;
    }

    compile(templateOrFragment, ctx = null, viewSlot = null):any {
        if (typeof templateOrFragment === "string") {
            var temp = document.createElement('span');
            temp.innerHTML = templateOrFragment;
            templateOrFragment = temp;
        }

        var view = this.viewCompiler.compile(templateOrFragment, this.resources).create(this.container, ctx);

        return view;
    }
}

I use this in Kendo in the cell template callback function (it lets you return a string that will become the cell contents)

function(dataItem) {
    var cellctx = { "$item": dataItem, "$parent": ctx };
    return this.compiler.compile(templateString, cellctx).fragment.innerHTML;
}

(this happens in Aurelia's bind callback so the ctx is the executionContext)

I just wrap the current data item up in a context and alias it as $item so I can work with it.

Looks something like this:

<kendo-grid>
    <kendo-grid-col title="Main Office" field="IsMainOffice">
        <kendo-template><img if.bind="$item.IsMainOffice" src="/content/img/accept.png" /></kendo-template>
    </kendo-grid-col>
</kendo-grid>

Upvotes: 2

Related Questions