Call vue method from inside kendo-ui grid col template - vue.js

I am trying to call a component method from inside a Kendo-UI grid column template, but I am getting a reference error. The problem is I have some global text formatting functions that I would like to share as a mixin. Is there anyway to call a vue component method from inside a grid col template?
<template>
<div>
<kendo-datasource ref="emailAccountDS"
:transport-read-url="'api/EmailAccounts'"
:transport-read-data-type="'json'"
:transport-read-type="'get'"
:type="'aspnetmvc-ajax'"
:schema-data="'data'"
:schema-total="schemaTotal"
:schema-model-id="'id'"
:schema-model-fields="schemaModelFields"
:server-paging= "true"
:server-sorting="true"
:server-filtering="true"
:page-size="25"
>
</kendo-datasource>
<kendo-grid :data-source-ref="'emailAccountDS'"
:pageable-always-visible="false"
:pageable-refresh="true"
:selectable="'row'"
:sortable="true"
:filterable="true"
:auto-bind="true"
:editable="'popup'"
:toolbar="['create','edit']">
<kendo-grid-column field="hostName" title="Host Name"></kendo-grid-column>
<!-- ReferenceError: testMethod is not defined -->
<kendo-grid-column field="accountType" title="Account Type" template="# testMethod(accountType) #"></kendo-grid-column>
<kendo-grid-column field="port" ></kendo-grid-column>
<kendo-grid-column field="useSsl"></kendo-grid-column>
<kendo-grid-column field="username"></kendo-grid-column>
</kendo-grid>
</div>
</template>
<script>
export default {
name: 'EmailAccounts',
data: function () {
return {
schemaModelFields: {
id: { type: 'number', editable: false, nullable: true },
isEnabled: { type: 'boolean', defaultValue: true, validation: { required: true } },
hostName: { type: 'string', validation: { required: true } },
port: { type: 'number', defaultValue: 995, validation: { required: true } },
useSsl: { type: 'boolean', defaultValue: true, validation: { required: true } },
username: { type: 'string', validation: { required: true } }
}
}
},
methods: {
testMethod(accountType) {//<=== ReferenceError: testMethod is not defined
return "foo";
},
schemaTotal: function (response) {
return response.total;
}
}
};
</script>
<style>
</style>
I have setup a plunker here that shows the same error.
I found this thread that said this should be working since 2018.1. This is version of kendo-ui I am running.
"dependencies": {
"#progress/kendo-datasource-vue-wrapper": "^2018.2.516",
"#progress/kendo-grid-vue-wrapper": "^2018.2.516",
"#progress/kendo-layout-vue-wrapper": "^2018.2.516",
"#progress/kendo-theme-default": "^2.53.1",
"#progress/kendo-treeview-vue-wrapper": "^2018.2.516",
"#progress/kendo-ui": "^2018.2.516",
"axios": "^0.18.0",
"element-ui": "^2.3.3",
"jquery": "^2.2.4",
"popper.js": "^1.13.0",
"vue": "^2.5.11",
"vue-awesome": "^2.3.5",
"vue-router": "^3.0.1",
"webpack-hot-middleware": "2.21.2"
},

Problem is that kendo template (with "# something #") "compiles" inside kendo code and there is no reference to your Vue app.
But in jquery-kendo docs I found that you can pass function to template. As I can see in kendo source code template function always should return not null/undefined value. So I added changes below and it works like a charm:
Changes in Vue template(bind template attr to function) <kendo-grid-column field="UnitsInStock" title="Units In Stock" :template="isInStock" :width="120"></kendo-grid-column>
Changes in Vue component code (slightly changed isInStock method to expect current data item object as in docs and made it always returns value):
isInStock: function(dataItem){
if(dataItem.UnitsInStock < 0 || !dataItem.UnitsInStock){
return "Out of stock";
}
return dataItem.UnitsInStock;
}

Related

How to append trigger property with createElement

<el-popover
ref="popover1">
<div>
content
</div>
</el-popover>
<el-button v-popover:popover1>Button</el-button>
I am not sure how to call v-popover:popover1 property but I want to ask how can I create such a property via createElement method dynamically?
return createElement('span', {}, [
createElement('el-popover', {
props: {
ref: component.props.ref,
}
}, 'content'),
createElement('el-button', {
props: {
'v-popover': component.props.ref
}
}, 'trigger')
])
Above way didn't work.
If you want to generate v-popover:popover1 in your template, you can do it via the directives property in createElement, i.e.:
createElement('el-button', {
directives: [
{
name: 'popover',
arg: component.props.ref
}
]
}, 'trigger')
The nomenclature of a VueJS binding:
v-popover:popover1
├─────┘ ├──────┘
└name └argument

How to bind nested JSON to Kendo Vue grid?

The below JSON is returned by a URL.
JSON:
{
"numberOfTransactions": 2,
"transactions": [
{
"Id": "1000497",
"officeShortId": "DRSD",
"procedureCode": "1234"
},
{
"Id": "1000497",
"officeShortId": "DRSD",
"procedureCode": "1234"
}
}
I want to bind all the fields inside "transactions" field to Kendo Vue grid.
I'm able to bind a simple JSON using this code but not able to bind the nested JSON.
It will be great if someone could help.
Vue Code:
import Vue from 'vue';
import { GridInstaller } from '#progress/kendo-grid-vue-wrapper';
import { DataSourceInstaller } from '#progress/kendo-datasource-vue-wrapper';
import '#progress/kendo-ui';
Vue.use(GridInstaller)
Vue.use(DataSourceInstaller);
export default {
data(){
return{
schemaModelFields: {
patientId: {editable: false, nullable: false },
officeShortId: { editable: false, nullable: false },
procedureCode: {editable: false, nullable: false}
}
}
}
}
<template>
<div>
<kendo-datasource ref="datasource1"
:transport-read-url="'someURL'"
:transport-read-data-type="'jsonp'"
:schema-model-id="'id'"
:schema-model-fields="schemaModelFields"
:batch='true'
:page-size='10'>
</kendo-datasource>
<kendo-grid :height="600"
:data-source-ref="'datasource1'"
:pageable='true'>
<kendo-grid-column :field="'patientId'" :width="120"></kendo-grid-column>
<kendo-grid-column :field="'officeShortId'"
:title="'id'"
:width="120"></kendo-grid-column>
<kendo-grid-column :field="'procedureCode'"
:width="120"></kendo-grid-column>
</kendo-grid>
</div>
</template>

Binding VueJS data variable to iFrame src

I am using YouTube iFrame to embed YouTube player into my NuxtJS application. videoId is passed as property to the component. And then URL is constructed and returned as data property to src attribute of iFrame.
YoutubePlayer.vue
props: {
videoId: {
type: String,
required: true
}
},
data() {
return {
videoUrl:
"https://www.youtube.com/embed/" +
this.videoId+
"?autoplay=1&origin=http://example.com"
};
}
<template>
<div class="iframeContainer">
<iframe
id="ytplayer"
width="640"
height="360"
:src="videoUrl"
></iframe>
</div>
</template>
But this is not working. What am I doing wrong?
UPDATE: No error in the console and nothing on the screen.
Can you try to check this?
props: {
videoId: {
type: String,
required: true
}
},
data() {
return {
videoUrl: '',
};
},
watch: {
videoId: function(newVal) {
this.videoUrl = "https://www.youtube.com/embed/" +
newVal +
"?autoplay=1&origin=http://example.com"
}
}

Kendo-UI Edit template not working with Vue Template Single File Component

I am using kendoui grid vue wrapper, I find out at kendoui vue documentation that I can use a single file Component for kendo templates, I am working on a editable grid with a popup editor, what I am doing is setting the property "editable" with the name of the method that return the template and template args, the same thing as the documentation of Vue Templates of KendoUi, but It just ignore the function and get inline editable.
The other way that I tried is to set the editable property like "{mode: 'popup', template: templateMethod}", and it popup the editing window, but at the content it just displays "[object] [object]".
Here is my Code:
RouterComponent:
<template>
<c-main>
<c-row>
<c-col xs="24" sm="8">
<c-panel title="Departamento<small>Workflow</small>" style="height:350px;">
<div class="u-mt-10"><strong>Nombre</strong></div>
<div class="u-mt-10">{{ $route.params.name }}</div>
<div class="u-mt-10"><strong>Descripción</strong></div>
<div class="u-mt-10">{{ $route.params.description }}</div>
</c-panel>
</c-col>
<c-col xs="24" sm="16">
<c-panel title="Usuarios<small>Administrar</small>" style="height:350px;">
<kendo-datasource
ref="usersdatasource"
:type="'aspnetmvc-ajax'"
:pageSize="20"
:server-filtering='true'
:transport-read-url= "baseServiceUrl+'/api/DepartmentUsers'"
:transport-read-type="'GET'"
:transport-read-data-type="'json'"
:transport-read-data="dataParameters"
:transport-destroy-url="baseServiceUrl+'/api/DepartmentUsers'"
:transport-create-url="baseServiceUrl+'/api/DepartmentUsers'"
:schema-data= "'Data'"
:schema-total= "'Total'"
:schema-errors= "'Errors'"
:schema-model-id="'Id'"
:schema-model-fields="usersSchemaModelFields"
></kendo-datasource>
<kendo-grid
id="usersdatagrid"
:height="'auto'"
:dataSourceRef="'usersdatasource'"
:toolbar="[ {name:'create', text: 'Agregar Usuario'}]"
:groupable='false'
:sortable='true'
:filterable='true'
:selectable='true'
:editable="{ mode: 'popup', template: popupTemplate }"
:pageable-refresh='true'
:pageable-page-sizes='true'
:pageable-button-count="5"
>
<kendo-grid-column
field="UserName"
title="Usuario"
>
</kendo-grid-column>
<kendo-grid-column
field="DisplayName"
title="Nombre"
>
</kendo-grid-column>
<kendo-grid-column
:width="150"
:command="[{name:'destroy', text:'Eliminar' }]" title="Acción">
</kendo-grid-column>
</kendo-grid>
</c-panel>
</c-col>
</c-row>
<c-row>
<c-col xs="24">
<c-panel title="Reglas<small>Departamento</small>" style="height:400px;">
<kendo-datasource
ref="rulesdatasource"
:type="'aspnetmvc-ajax'"
:pageSize="20"
:server-filtering='true'
:transport-read-url= "baseServiceUrl+'/api/Departments'"
:transport-read-type="'GET'"
:transport-read-data-type="'json'"
:transport-update-url="baseServiceUrl+'/api/Departments'"
:transport-update-type="'PUT'"
:transport-update-data-type="'json'"
:transport-destroy-url="baseServiceUrl+'/api/Departments'"
:transport-create-url="baseServiceUrl+'/api/Departments'"
:schema-data= "'Data'"
:schema-total= "'Total'"
:schema-errors= "'Errors'"
:schema-model-id="'Id'"
></kendo-datasource>
<kendo-grid
id="rulesdatagrid"
:height="'auto'"
:dataSourceRef="'rulesdatasource'"
:groupable='false'
:sortable='true'
:filterable='true'
:selectable='true'
:pageable-refresh='true'
:pageable-page-sizes='true'
:pageable-button-count="5"
>
<kendo-grid-column
field="UserName"
title="Usuario"
>
</kendo-grid-column>
<kendo-grid-column
field="Nombre"
title="DisplayName"
>
</kendo-grid-column>
</kendo-grid>
</c-panel>
</c-col>
</c-row>
</c-main>
</template>
<script>
import Vue from 'vue'
import UserTemplateVue from './departmentUserTemplate.vue'
var UserTemplate = Vue.component(UserTemplateVue.name, UserTemplateVue)
export default {
name: "AddUserDepartmentView",
data() {
return {
baseServiceUrl: window.baseServiceUrl,
dataParameters: {
department: $route.params.Id,
roles: "WORKFLOW;WORKFLOWADMIN"
},
filterConfiguration: [],
usersSchemaModelFields: {
Id: { editable: false, nullable: true },
DisplayName: { validation: { required: true } },
UserName: { validation: { required: true } },
Email: { validation: { required: true } },
TenantId: { validation: { required: true } },
IsAdmin: { validation: { required: true } }
}
}
},
methods: {
popupTemplate: function(e) {
return {
template: UserTemplate,
templateArgs: e
}
}
}
};
</script>
<style>
#usersdatagrid{
height:100% !important;
}
#rulesdatagrid{
height:100% !important;
}
</style>
Template Component:
<template>
<span>
<button #click="buttonClick">Click Me</button>
</span>
</template>
<script>
export default {
name: 'template1',
methods: {
buttonClick: function (e) {
alert("Button click")
}
},
data () {
return {
templateArgs: {}
}
}
}
</script>
Please Help me With this.
Thank You a lot
I know this is old, but I stumbled across this while looking for something related, so I thought I'd take a stab at it for future reference.
Two things I would suggest trying here:
Make sure that your component has a name specified.
Try using: editable-mode="popup;" along with editable-template="popupTemplate"
That did the trick for me. For whatever reason, it just wasn't happy when I was passing an object into editable.
Hope that helps!

Vue 2.5: Passing prop to component. Prop gets bundled in variable name

I'm new to Vue.js and my first try is to make a simple line-chart using ChartJS (vue-chartjs bundle).
I've used the "HelloWorld.vue" as base material, and created a LineChart.js
The problem is that in HelloWorld, i got my variable called datacollection, this name gets passed into my LineChart.js. How do I fix so I dont get the variable name as an object
I get:
datacollection:
{
labels: {...},
datasets: {...}
}
I want:
{
labels: {...},
datasets: {...}
}
Thus, in my LineChart.js I need to do .datacollection. This will make my LineChart.js less reusable, since I always have to remember to name all my variables calling LineChart 'datacollection'.
LineChart.js:
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props: ['data', 'options'],
watch: {
'data': function (value) {
// I get the update from backend, but I have to use .datacollection (the variable name from the calling page)
console.log('Ändrat: ', value)
this.renderChart(value.datacollection, this.options)
}
},
data () {
return {
gradient: null,
gradient2: null
}
},
mounted () {
console.log('data in component', this.data)
/*
this.data contains datacollection: {
labels: {
...
},
datasets: {
....
}
}
This wont render any graph since I dont do .datacollection
*/
this.renderChart(this.data, this.options)
}
}
My Graph.vue page:
<template>
<div class='hello'>
<h1>{{ msg }}</h1>
<h2>Graph</h2>
<!-- this.datacollection is printed as expected, {labels: {}, datasets: {}} -->
<p>{{ this.datacollection }}</p>
<section>
<line-chart
:data='{datacollection}'
:options='{chartOptions}'
:width="400"
:height="200"
>
</line-chart>
</section>
<section>
<reactive-example></reactive-example>
</section>
</div>
</template>
<script>
export default {
name: 'Graph',
mounted: function () {
this.axios.get('graph/').then(response => {
console.log(response.data)
this.datacollection = response.data
})
},
data: function () {
return {
msg: 'Welcome to Your Vue.js App',
datacollection: {
labels: ['January', 'February'],
datasets: [
{
label: 'First',
backgroundColor: '#f87979',
data: [40, 20]
},
{
label: 'Second',
backgroundColor: '#aa7979',
data: [20, 30]
}
]
}
}
}
}
</script>
<!-- Add 'scoped' attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
My dependenicies (versions)
"dependencies": {
"axios": "^0.17.1",
"chart.js": "^2.7.1",
"vue": "^2.5.2",
"vue-axios": "^2.0.2",
"vue-chartjs": "^3.0.2",
"vue-router": "^3.0.1"
}
What do I miss?
In your template, you have the following:
<line-chart
:data='{datacollection}'
:options='{chartOptions}'
:width="400"
:height="200"
>
</line-chart>
In ES2015, {datacollection} is shorthand (see New notations in ECMAScript 2015) for creating a new object with a datacollection property with the value of datacollection as its value. In Vue, everything in the quotes of a binding is treated as a javascript expression, so in most modern browsers what that syntax does is create a new object with a datacollection property and pass that object to the component.
Instead, just remove the braces.
<line-chart
:data='datacollection'
:options='chartOptions'
:width="400"
:height="200"
>
</line-chart>