Campbeln
Campbeln

Reputation: 2990

How to use child <template> tags per directive/component invocation to create dynamic templates?

I'm trying to port an AngularJS directive over to VueJS, but I have been unable to crack this particular nut...

To put it simply, I have a "generic" list directive. Under each invocation of the directive is a <template> tag that defines how the tbody is rendered. In AngularJS I was able to accomplish this by DOM-replacing the tbody[target='true'] in #myDirectiveBaseTemplate with the contents of my-directive > template per invocation of <my-directive> (plus a little $compile service majic mixed in to make it a-go-go).

VueJS doesn't seem to give me access to this low-level functionality, or when it (kinda sorta) does it doesn't give me a reference to the current _element so I do not have access to each invocation's <template> tag.

The simplified AngularJS directive code is defined something like this:

<my-directive data="some.list" mapping="[ 'property', 'property2' ]">
    <template>
        <tbody>
            <tr ng-repeat="item in data">
                <td>{{item.property}}</td>
                <td>{{item.property2}}</td>
            </tr>
        </tbody>
    </template>
</my-directive>

myDirective first pulls in the base text/ng-template, which looks something like this:

<script type="text/ng-template" id="myDirectiveBaseTemplate">
    <table>
        <thead>
            <tr ng-repeat="prop in mapping" ng-click="doSort(prop)">
                {{prop}}
            </tr>
        </thead>
        <tbody target="true"></tbody>
    </table>
</script>

During render, tbody[target='true'] in #myDirectiveBaseTemplate is DOM-replaced with each invocation's my-directive > template whereby creating custom HTML for each invocation of my-directeive based on each embedded template.

So... how in the hell do I accomplish this in VueJs?!?

EDIT 1:

A Second invocation of my-directive could looks like this:

<my-directive data="some.list" mapping="[ 'order.delivered', 'person.name', 'person.dob' ]">
    <template>
        <tbody>
            <tr ng-repeat="item in data">
                <td>{{item.order.delivered ? 'Delivered' : ''}}</td>
                <td>{{item.person.name}}</td>
                <td>{{item.person.dob | format:'yyyy-mm-dd'}}</td>
            </tr>
        </tbody>
    </template>
</my-directive>

And just to note, the example above has been simplified. my-directive actually can define up to 5 different <template>s within itself to modify various parts of the "generic" list (e.g. <template type='row'>, <template type='help'>, etc.). However, all serve the same purpose; to modify/add-to various parts of the DOM of the underlying directive's HTML.

Upvotes: 0

Views: 63

Answers (1)

Nati Mask
Nati Mask

Reputation: 676

I weren't able to understand if there is a case when your <template> is going to create "custom HTML for each invocation of my-directive" except of showing different item properties at each table row. If this only the difference between invocations so your Vue.js components templates could simply look like:

Vue.js ChildTbodyComponent.vue Template:

<tbody>
    <tr v-for="item in items" :key="item.id">
        <td>{{item.property}}</td>
        <td>{{item.property2}}</td>
    </tr>
</tbody>

Vue.js ParentTableComponent.vue Template:

<table>
    <thead>
        <tr v-for="header in headers" :key="header.name" @click="doSort(header)">
            {{header.name}}
        </tr>
    </thead>
    <child-tbody-component :items="arrayOfDataForRows"></child-tbody-component>
</table>

Upvotes: 1

Related Questions