How i can use a router-link in kendo grid (vuejs) - vue.js

How i can use <router-link to="/detail/1">Details</router-link> with Kendo Grid?
I want use the standard logic of a normal link in the grid, with no reload of the full page on click. I have try to use router-link inside the grid with a template but it's doesn't work. Also no error in available in console.
Example on Stackblitz
Update 24 October 2018
Kendo Grid for Vue is initializing a plain Kendo Grid widget for jQuery.
Thus, all templates are evaluated runtime and possible routes cannot be evaluated afterwards or the router-link elements to be resolved.
If you have the same problem Vote for this suggestion
vue native implementation

It is true that you cannot use router-link inside a kendo template. But I thought I would offer an alternative way to achieve the same result.
You can redirect to the new page using the programmatic way by calling router.push({ path:/detail/${id}}).
Replace the template with a command that implements a click event, and call route.push from there.
I have updated your example on slackblitz with a working example.
Kendo Grid with command col
<kendo-grid ref="grid"
:height="550"
:data-source-ref="'datasource1'"
:sortable="true">
<kendo-grid-column :field="'ProductID'"
:title="'Product ID'"></kendo-grid-column>
<kendo-grid-column :field="'ProductName'"
:title="'Product Name'"></kendo-grid-column>
<kendo-grid-column :field="'Link'" :template="linkTemplate1"></kendo-grid-column>
<kendo-grid-column :command="detailsLink"></kendo-grid-column>
</kendo-grid>
Command array in the data object.
new Vue({
el: '#vueapp',
router,
data () {
return {
linkTemplate1: "<a href='/detail/#:ProductID#' class='k-button'>Link</a>",
detailsLink: [{
name: "details",
click: function(e) {
// prevent page scroll position change
e.preventDefault();
var tr = $(e.target).closest("tr"); // get the current table row (tr)
// get the data bound to the current table row
var data = this.dataItem(tr);
// redirect to new page
router.push({ path: `/detail/${data.ProductID}` })
},// template must include k-grid-[command name]
template: "<a class='k-button k-grid-details'>TEST</a>"
}]
}
}
})

Related

Vue and Fullcalendar customizing day cell

I need to add a button into every day cell. I know that I can do something similar to this:
dayCellContent: {
html: `<button> button text </button>`,
},
But i don't really wanna do that and I would much rather use my button component. Also like this I would have to add the click listeners without Vue which I also don't like very much.
So is there a better way to do this? Preferably just pass in the Vue component?
I solved this by using a component and initializing it using the Vue constructor like so.
const el = document.createElement("a");
const calendarDayCellContentContainer = new Vue({
el,
render: (h) =>
h(CalendarDayCellContent, {
props: {
buttonText: "whatever",
},
}),
});
and passing the button.$el as DOM node.
domNodes: [button.$el],

Generate Vue Component with vanilla JS

I am currently using the bootstrap table component to display a list (bootstrap-table.com)
This component (or jQuery plugin wrapped within a vue component) has a formatter for each column.
example with source code: https://examples.bootstrap-table.com/#welcomes/vue-component.html#view-source
I need to build a more complex set of links which involve some js processing that could easily be done with vue.
Instead of the formatter returning the <a> tag I would like to return the contents of a <component>. I have tried this but haven't been able to render a component.
I'm almost sure this is impossible because the child component is not previously binded which means the component won't be "reactive".
As an alternative I can build a js function that generates all the required links.
Another phrasing for this question would be: Is there any possibility to generate a vue component from vanilla js?
The above was not possible the way was tried because the components cannot be simply rendered like html tags as they can have methods and computed data therefore they must be compiled.
It looks like the solution for the above situation is using the Vue.compile() method:
const template = `
<ul>
<li v-for="item in items">
{{ item }}
</li>
</ul>`;
const compiledTemplate = Vue.compile(template);
new Vue({
el: '#app',
data() {
return {
items: ['Item1', 'Item2']
}
},
render(createElement) {
return compiledTemplate.render.call(this, createElement);
}
});
Demo:
https://codepen.io/couellet/pen/ZZNXzy
Demo reference:
https://snipcart.com/blog/vue-render-functions
Vue docs:
https://v2.vuejs.org/v2/api/#Vue-compile

vue: design a dynamic "window" component like bootstrap modal

I am trying to create a generic HTML Window from Vue application.
What I want
I click "edit" on item from list, a DHTML popup will be opened with a Vue component inside. I can click Save or close the opened component need to removed from the page and may the caller recive a event/promise with resolve (Save) or reject (Close).
What I am tried
I was started via DOM:
function Win(vueapp,obj) {
var div = document.createElement("div");
var Win = JQueryOldFunction()
//need a way to resolve when the user hit 'Save' and reject when closing
var resolve,reject, promise = new Promise(function(a, b) {
resolve=a, reject=b;
});
new Vue({
el: div,
data: {data:obj} //need a way to pass it to the component
render: function (h) {
return h("m");
},
components: {
'm': httpVueLoader(vueapp+'.vue') // this from https://github.com/FranckFreiburger/http-vue-loader
}
});
return promise;
}
This is working, but I can't use Vue to destroy the window after clicking save, and can't pass objects inside
so I was tried other option:
<component :is="gui.window" transition="fade" transition-mode="out-in"></component>
Model.gui.window='EditGroup'
(took from here: https://coligo.io/dynamic-components-in-vuejs/ )
This is better, it working, does not allowing more than one window, but the internal component can't destroy itself.

Does Vue have bilateral bind?

<p contenteditable="true" v-bind="message"></p>
Object #message does not change when I edit the HTML element. Is there any simple way to do this using Vue.js?
Unfortunately, contenteditable doesn't work with Vue bindings such as v-model, it's recommended that you use a library such as medium.js to build your own component.
However, if you're just trying to do something simple and keep the data in sync you can probably do that yourself:
View Model
new Vue({
el: '#app',
methods: {
updateMessage() {
this.message = this.$refs.message.innerText;
}
},
watch: {
message() {
this.$refs.message.innerText = this.message;
}
},
data: {
message: 'Hello'
}
})
HTML
<p ref="message" contenteditable="true" #keyup="updateMessage" class="editable">{{message}}</p>
 
As you can see you have to deal with updating the DOM yourself when using contenteditable. What I'm actually doing here is using a ref to target the contenteditable, so I can get the inner text via this.$refs.message.innerText. I've then added a #keyup event which calls the updateMessage method to update the message data property. I've then added a watcher which reverses this process, so when message is updated it updates the contenteditable.
Here's the JSFiddle: https://jsfiddle.net/3ngc9486/
Yes it has a two-way binding directive v-model, but it works only with input elements. So, instead of using a p element and handling that with complex JS, use a textarea with v-model and it will work out of the box.
<textarea v-model="message"></textarea>
here is an example.

How do I update semantic ui dropdown list with vue?

I'm trying to update the semantic ui dropdown with new values. Vue is correctly being updated and I'm refreshing the semantic ui dropdown but it still isn't updating. I saw another post which mentioned the use of key, but it still fails.
Template
<div id=root>
<label>Type:</label>
<select id="app_type" class="ui search selection dropdown" v-model="model_type_val">
<option v-for="model_type in model_types" v-bind:value="model_type.value" v-bind:key="model_type.value">{{model_type.text}}</option>
</select>
<p>
selected: {{model_type_val}}
</p>
</div>
Code
var model_types2= [
{value:"",text:"Type"},
{value:"type1",text:"Type1a"},
{value:"type2",text:"Type2a"},
{value:"type3",text:"Type3a"},
{value:"type4",text:"Type4"}
];
var vm2= new Vue({
el:'#root',
data:{
model_type_val:"",
model_types:[
{value:"",text:"Type"},
{value:"type1",text:"Type1"},
{value:"type2",text:"Type2"},
{value:"type3",text:"Type3"}
]
},
mounted: function(){
$('#app_type').dropdown();
setTimeout(function() {
this.model_types=model_types2;
alert(this.model_types[1].text);
$('#app_type').dropdown('refresh');
}, 1000);
}
});
I've tried to reproduce the code in this jsfiddle.
You have a this problem. When you have a callback inside a Vue method or lifecycle hook in which you use this, you need to make sure that this points to the correct object (the Vue). You do that with an arrow function, a closure, or bind.
setTimeout(() => {
this.model_types=model_types2;
$('#app_type').dropdown('refresh');
}, 1000);
Here is your fiddle updated.
Note: In the fiddle, I also converted your selector to use a ref. Typically you want to start weaning yourself off jQuery when working with Vue.
See How to access the correct this inside a callback.