How to bind nested JSON to Kendo Vue grid? - vue.js

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>

Related

How to dynamically insert text in Ckeditor5 for Vue 2

My application provides many selectable standard paragraphs which users can insert at any point. In a previous version insertion was simple: CKEDITOR.instances[editorId].insertHTML(text).
I'm trying to use v5 api with model.insertContent(text) but get error:
"vue.runtime.esm.js:3020 TypeError: t2.is is not a function
at bl.rp (converters.js:771:21)
at bl.fire (emittermixin.js:199:30)
at <computed> (observablemixin.js:262:16)
at VueComponent.testInsert (Test.vue:29:1)"
Here's the composition file. I have tried accessing the insertContent method from this.editor and from the apiReference returned from the #ready event;
<template>
<div>
<button #click="testInsert('abracadabra')">Insert literal content</button>
<ckeditor tag-name="textarea" :editor="editor" v-model="doc.HTML" #ready="editorReady" :config="editorConfig"></ckeditor>
</div>
</template>
<script>
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
export default {
name: 'testEditorInsert',
mounted() {
},
data() {
return {
doc: {ID: 0, HTML: "This is a sample text. Insert here? This is the remainder of the sample text"},
editor: ClassicEditor,
editorData: 'loading',
editorConfig: {
toolbar: [ 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote' ],
},
editorApi:null ,
}
},
methods: {
testInsert: function(text) {
console.log(this.editorApi, text);
//this.editor.model.insertContent(text);
this.editorApi.model.insertContent(text);
},
editorReady: function(editor) {
this.editorApi = editor;
}
},
}
</script>

Custom Kendo Vue Grid Wrapper Column Template Using kendo-grid columns Attribute

I have the following template that I would like to use to render the contents of a Kendo grid wrapper cell:
<template>
<span>
Template Rendered: {{ templateArgs.name }}
</span>
</template>
<script>
export default {
name: 'template1',
data () {
return {
templateArgs: {}
}
}
}
</script>
I am able to do this using kendo-grid-column elements as follows:
<template>
<div>
<kendo-grid :data-source="datasource">
<kendo-grid-column field="name" title="Name" :template="itemTemplate"></kendo-grid-column>
</kendo-grid>
</div>
</template>
<script>
import Vue from 'vue'
import { Grid, GridColumn } from '#progress/kendo-grid-vue-wrapper'
import Template from './Template.vue'
var itemTemplate = Vue.component(Template.name, Template)
export default {
name: 'HelloWorld',
components: {
'kendo-grid': Grid,
'kendo-grid-column': GridColumn
},
methods: {
itemTemplate: function (e) {
return {
template: itemTemplate,
templateArgs: e
}
}
},
data () {
return {
datasource: [ { name: "Jane Doe" }, { name: "John Doe" } ]
}
}
}
</script>
I would like to use the kendo-grid columns attribute instead, as follows:
<template>
<div>
<kendo-grid :data-source="datasource" :columns="columns">
</kendo-grid>
</div>
</template>
<script>
import Vue from 'vue'
import { Grid, GridColumn } from '#progress/kendo-grid-vue-wrapper'
import Template from './Template.vue'
var itemTemplate = Vue.component(Template.name, Template)
export default {
name: 'HelloWorld',
components: {
'kendo-grid': Grid,
'kendo-grid-column': GridColumn
},
methods: {
itemTemplate: function (e) {
return {
template: itemTemplate,
templateArgs: e
}
}
},
data () {
return {
columns: [{ field: "name", title: "Name", template: this.itemTemplate }],
datasource: [ { name: "Jane Doe" }, { name: "John Doe" } ]
}
}
}
</script>
Something is wrong with the code in the second case, though. Instead of rendering the cells using the template, I am getting [object Object] as the cell contents. What should I do in order to fix this?
Using the columns property when using custom render templates is not supported by the Vue grid wrapper. Something similar can be done with a native grid, however.
Source: https://www.telerik.com/forums/custom-kendo-grid-wrapper-column-template-using-kendo-grid-columns-attribute

Vuejs component doesn't update when changing variable

I'm learning Vue.js and have been able to write a simple list/detail application. Selecting the first item renders the detail component with the correct data, however when I select a different item the detail component doesn't reload with the right information.
For example:
<template>
<div>
<detail :obj="currentObject"></detail>
</div>
</template>
<script>
export default: {
data: function(){
return {
currentObject: null,
objs = [
{name:'obj 1'},
{name:'obj 2'}
]
};
}
}
</script>
When I do this.currentObject = objs[0] the component detail updates with the correct content. However the next time I call this.currentObject = objs[1], the component detail no longer updates.
Not sure what's the context your are switching the data on your currentObject, but the below is a concept detail component and when you switch the objs it updated the prop :obj and seems working fine.
Looking at your code, you should declare objs using : not =.
data: function() {
return {
currentObject: null,
objs: [
{name:'obj 1'},
{name:'obj 2'}
]
};
}
Here is the concept detail component, run the snippet to check it working.
Vue.component('detail', {
props: ['obj'],
template: '<div>{{ obj }}</div>'
})
var app = new Vue({
el: '#app',
data() {
return {
bToggle: false,
currentObject: null,
objs: [
{name:'obj 1'},
{name:'obj 2'}
]
}
},
created(){
this.switchData();
},
methods: {
switchData() {
if(!this.bToggle){
this.currentObject = this.objs[0];
}else{
this.currentObject = this.objs[1];
}
this.bToggle = !this.bToggle;
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<div id="app">
<button #click="switchData()"> switch </button>
<detail :obj="currentObject"></detail>
</div>

Unable to trigger render when switching between multiple objects containing content in different languages

I read Reactivity in Depth but can't solve the issue.
I'm creating a small single page app that contains images and text.
When the user clicks a button I want the language to change.
Currently I am storing the content in two files that export an object.
export default {
projects: [
{
title: 'Project Title',
year: 2016,
...
},
]
}
and importing that
import contentEn from './assets/content.en.js'
import contentDe from './assets/content.de.js'
new Vue({
el: '#app',
components: { App },
data: {
mainContent: {
content: contentEn
}
},
methods: {
switchToGerman(){
this.mainContent.content = contentDe
}
},
template: '<App :mainData="mainContent"/>',
})
When I assign another object to mainContent.content the rendering is not triggered.
I understand that adding and deleting properties from object don't lead to change detection but I switch out a whole object. I tried assigning it with this.$set with no success.
I also tried this and googled a lot but can't get it work.
Or is my approach just wrong?
Thank you for helping,
best,
ccarstens
EDIT:
See below the code for the App component and the ProjectElement
// App.vue
<template>
<div id="app">
<button #click="switchGerman">Deutsch</button>
<ProjectElement v-for="(project, key) in fullData.content.projects" :key="key" :content="project"/>
</div>
</template>
<script>
import ProjectElement from './components/ProjectElement'
export default {
name: 'App',
props: [
'mainData'
],
data () {
return{
fullData: {}
}
},
methods: {
switchGerman(){
this.$root.switchToGerman()
}
},
created(){
this.fullData = this.$props.mainData
},
watch: {
mainData: {
handler: function(newData){
this.fullData = newData
},
deep: true
}
},
components: {
ProjectElement,
}
}
</script>
And the ProjectElement
//ProjectElement.vue
<template>
<article :class="classObject" v-observe-visibility="{
callback: visibilityChanged,
throttle,
intersection: {
threshold
}
}">
<header v-html="description"></header>
<div class="content">
<carousel :per-page="1" :pagination-enabled="false">
<slide v-for="(slide, index) in projectContent.media" :key="index">
<VisualElement :content="slide" ></VisualElement>
</slide>
</carousel>
</div>
</article>
</template>
<script>
import {Carousel, Slide} from 'vue-carousel'
import VisualElement from './VisualElement'
export default {
name: "ProjectElement",
components: {
Carousel,
Slide,
VisualElement
},
props: [
'content'
],
data () {
return {
projectContent: {},
isVisible: false,
throttle: 300,
threshold: 0.8
}
},
created(){
this.projectContent = this.content
},
methods: {
visibilityChanged(isVisible){
this.isVisible = isVisible
}
},
computed: {
description(){
return `
<p>${ this.projectContent.title } - ${this.projectContent.year}</p>
<p>${ this.projectContent.description }</p>
`
},
classObject(){
return {
visible: this.isVisible,
'project-element': true
}
}
}
}
</script>
Did you try doing deep copy:
switchToGerman () {
const copyContent = JSON.parse(JSON.stringify(this.mainContent))
copyContent.content = contentDe
this.mainContent = copyContent
}
I found the solution (thank you #EricGuan for pointing out that the mistake must lay somewhere else)
As you can see in the original post I created a watcher for the mainData property and expected that this would trigger the re render.
What was missing is, that I didn't watch the content property on the ProjectElement component, thus not triggering a re render there.
I added this to ProjectElement.vue and now it works like a charm:
watch: {
content(newContent){
this.projectContent = newContent
}
},
Thank you everybody for helping me! <3

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!