4

I'm following the example here of using a Vue template as a Kendo UI template in their components:

https://www.telerik.com/kendo-vue-ui/components/framework/vue-templates/

The example isn't very clear on how to supply properties to components that are rendered with this method (as opposed to rendering right in the template). I need to supply a single value determined in the parent to all instances of this child component, and I also need to subscribe to emitted events from the child component. My assumption is that there's an overload to Vue.component() that lets me access this functionality?

Edit: Specifically what I am looking for is a way to have a header template for each column created from a Vue component. I need each column's template to receive data from the parent so I know how to construct it, and I also need each column's template to report an event back to the parent.

Mike Cole
  • 14,474
  • 28
  • 114
  • 194
  • " that are initialized in this matter." ... what does that mean? Also, at a quick glance it seems okay to me, you pass properties to parent element using `:prop='value'` which you can see in the example – samayo Mar 27 '18 at 16:40
  • Meaning I'm much more familiar with using components in a template like so: `` – Mike Cole Mar 28 '18 at 19:33
  • I'm unfamiliar with using them the way this example illustrates and I'm not sure how to pass in parms or subscribe to emitted events. – Mike Cole Mar 28 '18 at 19:34
  • it is using it the same way you are using it – samayo Mar 28 '18 at 19:35
  • In the link, the component in question is not kendo-dropdownlist, it's the template that kendo-dropdownlist is using. – Mike Cole Mar 28 '18 at 19:38
  • I think it is. It's only telling you how to initiate it and which dependencies it has – samayo Mar 28 '18 at 19:40
  • I'm going to need more clarification. I'm way lost. – Mike Cole Mar 28 '18 at 20:01
  • check [vue-kendo sand box](https://codesandbox.io/s/jvll79xpn3) simply forked the codes from below answer, then added MyTemplate.vue, and added some codes in DropdownStyles.vue, you will see the third dropdownlist will have one button and render with the value from parent. Most likely it is what you are looking for. – Sphinx Apr 28 '18 at 01:14
  • 1
    @MikeCole, I just thought out one approach if you'd like uses built in props, but probably make the things complicated. we can create one component as template, for that template, only has one div with one specific class like `your-template`, – Sphinx May 04 '18 at 21:12
  • 1
    @MikeCole then in parent component, call `let childBuilder = Vue.extend(realComponentOptions); for(item of document.getElementsByClassName('your-template')) { let yourChild = new childBuilder() yourChild.$mount() item.appendChild(yourChild.$el) }` to mount your real component (you can save all childs into one data property), then change the props at parent component by `yourChild[index].$props` – Sphinx May 04 '18 at 21:13

3 Answers3

1

I think the key point is Step 3 in the link you attached (Kendo Vue Template Usage). (Never touch Kendo Before, if anything wrong, correct me, thanks.)

First, please open this Vue kendo Sandbox, you will find one dropdownlist then each option is one button plus one text. If you click the button, it will call one method in MyTemplate.vue and another Method at DropDownStyle.vue, then its background of each option is blue which passed from DropDownStyle.vue.

Kendo will bind this function of Step 3 to its attribute=template, then fisrt parameter (and only one) is each element of the data-source.

Then this function need to return one object including template and templateArgs, then Kendo construct it.

So my solution is add your function/callback/styles into templateArgs, then do what you need at MyTemplate.vue.

Below is the codes extended from Step 3.

  methods: {
    getMyTemplate: function (e) {
      // parameter=e: it is the value of each element of the dropdown
      e.callback = this.eventCallback
      e.styles="background-color:blue"
      return {
            template: MyTemplate,
            templateArgs: e
        }
    },
    eventCallback: function (data) {
      console.log(this.dropdowns)
    }
  }

Below is MyTemplate.vue.

<template>
    <span :style="templateArgs.styles">
        <button @click="buttonClick();templateArgs.callback()">{{templateArgs.value}}</button>
        {{templateArgs.text}}
    </span>
</template>

<script>
export default {
    name: 'template1',
    methods: {
        buttonClick: function (e) {
            console.log('props',this.templateArgs.styles)
        }
    },
    data () {
      return {
          templateArgs: {
            callback:function(){
              console.log('Test')
            },
            styles:''
          }
      }
    }
}
</script>
Sphinx
  • 10,519
  • 2
  • 27
  • 45
1

Very odd design choice in terms of passing the template in like they do. Avoiding the KendoUI and focusing on VueJS methods - could you use provide/inject? Providing the value in the parent and injecting in any of the children?

Also a plugin could be created to keep track of events or values you want available to all components in the application. In essence the plugin would be a service. A singleton object that is only instantiated once.

tony19
  • 125,647
  • 18
  • 229
  • 307
A. Hall
  • 71
  • 4
0

The documentation is indeed lacking. I agree with you on that. I took a different approach with templating for Kendo UI component and got this working: https://codesandbox.io/s/github/ariellephan/vue-kendoui-template

To start, I have this dropdown component that utilizes Kendo dropdown list component:

<template>
  <div>
    <p>Style with template {{template}}</p>
    <kendo-dropdownlist 
                    :template="template"
                    :headerTemplate="headerTemplate"
                    :data-source="dataSourceArray"
                    :data-text-field="'text'"
                    :data-value-field="'value'"
                    :filter="'contains'">
    </kendo-dropdownlist>
  </div>
</template>

<script>
export default {
  name: "Dropdown",
  props: ["dataSourceArray", "template", "headerTemplate"],
  data() {
    return {
      value: "Click Me",
      text: "I'm in Template template"
    };
  }
};
</script>

To render different styles/templates, I parsed in props from the parent component. In this case, DropdownStyles

<template>
  <div id="DropdownStyles">
    <h1>KendoUI dropdown instances with different templates</h1>
    <Dropdown
  v-for="dropdown in dropdowns"
  v-bind:key="dropdown.id"
  v-bind:title="dropdown.title"
  v-bind:data-source-array="dropdown.dataSourceArray"
  v-bind:template="dropdown.template"
  v-bind:headerTemplate="dropdown.headerTemplate"
></Dropdown>
  </div>
</template>

<script>
import Dropdown from "./Dropdown";
import DropdownTemplate from "./DropdownTemplate";

export default {
  name: "DropdownStyles",
  components: { Dropdown },
  data() {
    return {
      dropdowns: [
        {
          id: 1,
          title: "x style",
          dataSourceArray: [
            "Football",
            "Tennis",
            "Basketball",
            "Baseball",
            "Cricket",
            "Field Hockey",
            "Volleyball"
          ],
          template: `<strong class="custom-dropdown">x #:data#</strong>`,
          headerTemplate: DropdownTemplate.template
        },
        {
          id: 2,
          title: "+ style",
          dataSourceArray: [
            "Football",
            "Tennis",
            "Basketball",
            "Baseball",
            "Cricket",
            "Field Hockey",
            "Volleyball"
          ],
          template: `<strong class="custom-dropdown">+ #:data#</strong>`,
          headerTemplate: `<div><h3 style="padding-left:10px;">Sports 2</h3></div>`
        }
      ]
    };
  }
};
</script>

You can move the template into its own file or function. For example, the first drop down is using DropdownTemplate for its headerTemplate:

DropdownTemplate.vue

<script>
export default {
  name: "DropdownTemplate",
  props: ["header"],
  template: `<div>
    <div><h3>Sports 1</h3></div>
  </div>`,
  data() {
    return {};
  }
};
</script>
<style scoped>
h3 {
  padding-left: 10px;
}
</style>
Arielle Nguyen
  • 2,932
  • 1
  • 20
  • 15
  • Let me know if I'm looking at this incorrectly, but are you using a template string for both template and headerTemplate? I'm looking to use a Vue component because I need to pass in props and handle events. – Mike Cole Apr 27 '18 at 17:01
  • You can import template from another Vue component. I've updated the answer – Arielle Nguyen Apr 27 '18 at 20:38