Is there any possibility to create DataGrid cell with FileUpload associated with row.
For example I have database with records and I want to have a possibility to attach files to selected records.
Is someone know how to do that and can share with me ;)
Thanks a lot for your help :D
Do you mean something like this:
A simple demo:
<div class="demo-container">
<div id="gridContainer"></div>
</div>
<script>
$(function () {
var customers = [{
"ID": 1,
"CompanyName": "Premier Buy",
"Address": "7601 Penn Avenue South",
}, {
"ID": 2,
"CompanyName": "ElectrixMax",
"Address": "263 Shuman Blvd",
}, {
"ID": 3,
"CompanyName": "Video Emporium",
"Address": "1201 Elm Street",
}]
$("#gridContainer").dxDataGrid({
dataSource: customers,
showBorders: true,
columns: ["CompanyName", "Address", {
dataField: "COLUNIQID",
alignment: 'center',
caption: "Actions",
cellTemplate: function (container, options) {
$('<input type="file" />')
.on('change', function () {
//do the upload here
})
.appendTo(container);
}
}]
});
});
</script>
Related
Let me preface this by saying that I'm new to VueJS and I expect the solution to my problem is something trivial but I can't for the life of me figure it out or find it online so here I am :
I followed Traversy Media's crash course on VueJS and built the task tracker app alongside him and everything was working well. But after the course ended, I decided to play around with Data Tables in the About page, specifically, using tables that have column filtering. Two candidates came up : VueGoodTable and VueBootstrap4Table.
I know for a fact that VueGoodTable works because I had already used it before with Laravel without really understanding how any of it works, but when I tried to import it here, I kept getting this error :
Code:
<template>
<div class="about">
<h1>This is an about page</h1>
<vue-good-table
:columns="columns"
:rows="rows"/>
</div>
</template>
<script>
import 'vue-good-table/dist/vue-good-table.css'
import { VueGoodTable } from 'vue-good-table';
export default {
components: {
VueGoodTable,
},
data(){
return {
columns: [
{
label: 'Name',
field: 'name',
},
{
label: 'Age',
field: 'age',
type: 'number',
},
{
label: 'Created On',
field: 'createdAt',
type: 'date',
dateInputFormat: 'yyyy-MM-dd',
dateOutputFormat: 'MMM do yy',
},
{
label: 'Percent',
field: 'score',
type: 'percentage',
},
],
rows: [
{ id:1, name:"John", age: 20, createdAt: '',score: 0.03343 },
{ id:2, name:"Jane", age: 24, createdAt: '2011-10-31', score: 0.03343 },
{ id:3, name:"Susan", age: 16, createdAt: '2011-10-30', score: 0.03343 },
{ id:4, name:"Chris", age: 55, createdAt: '2011-10-11', score: 0.03343 },
{ id:5, name:"Dan", age: 40, createdAt: '2011-10-21', score: 0.03343 },
{ id:6, name:"John", age: 20, createdAt: '2011-10-31', score: 0.03343 },
],
};
},
}
</script>
This code is literally copy-pasted from the Get Started page of the VueGoodTable documentation.
A different error also happens when I try to use VueBootstrap4Table instead :
Code:
<template>
<div class="about">
<h1>This is an about page</h1>
<vue-bootstrap4-table :rows="rows" :columns="columns" :config="config">
</vue-bootstrap4-table>
</div>
</template>
<script>
import VueBootstrap4Table from 'vue-bootstrap4-table'
export default {
data: function() {
return {
rows: [{
"id": 1,
"name": {
"first_name": "Vladimir",
"last_name": "Nitzsche"
},
"address": {
"country": "Mayotte"
},
"email": "franecki.anastasia#gmail.com",
},
{
"id": 2,
"name": {
"first_name": "Irwin",
"last_name": "Bayer"
},
"age": 23,
"address": {
"country": "Guernsey"
},
"email": "rlittle#macejkovic.biz",
},
{
"id": 3,
"name": {
"first_name": "Don",
"last_name": "Herman"
},
"address": {
"country": "Papua New Guinea"
},
"email": "delia.becker#cormier.com",
}],
columns: [{
label: "id",
name: "id",
filter: {
type: "simple",
placeholder: "id"
},
sort: true,
},
{
label: "First Name",
name: "name.first_name",
filter: {
type: "simple",
placeholder: "Enter first name"
},
sort: true,
},
{
label: "Email",
name: "email",
sort: true,
},
{
label: "Country",
name: "address.country",
filter: {
type: "simple",
placeholder: "Enter country"
},
}],
config: {
checkbox_rows: true,
rows_selectable: true,
card_title: "Vue Bootsrap 4 advanced table"
}
}
},
components: {
VueBootstrap4Table
}
}
</script>
I'm guessing that I'm not importing these components correctly somehow, so I would appreciate any help with this.
Thank you.
The unfortunate fact is that "not so recent" release of Vue v3 has bring some breaking changes from Vue 2 which require some migration
It is safe to say that very little of the existing components and component libraries created for Vue 2 work without any modification in Vue 3
The repo linked to the course shows that you are using Vue 3. But Both the vue-good-table or vue-bootstrap4-table are Vue 2 components and do not have a version for Vue 3 yet
So you need to look for different component and look for explicit support of Vue 3...
I want to use the response coming from the API in v-select. Here is a scenario i want to use the API call from component A to component B, rather than calling it again in the component B.
Component A:
methods: {
forVselect (id) {
this.$http.get(`/type/${id}`)
.then((res) => {
this.icecream = res.data})
.catch((e) => {console.log(e)})
}
},
mounted (){
this.forVselect (this.$route.params.un_id)
}
Component B:
<template>
<div class="The V-select">
<vselect v-model="input1" :options="[{label: 'Vanilla' , value: 'vanilla'}]" :dir="$vs.rtl ? 'rtl' : 'ltr'" />
</div>
</template>
<script>
import vselect from 'vue-select'
...
input1: null,
icecream: null
...
methods: {
forVselect (id) {
this.$http.get(`/type/${id}`)
.then((res) => {
this.icecream = res.data})
.catch((e) => {console.log(e)})
}
},
mounted (){
this.forVselect (this.$route.params.un_id)
}
</script>
As you can see my Component B i have hard coded as 'vanilla' in v-select, rather i want to use the data coming from the API, i want to know how it can be done.
Here is my Api response:
[
{
"id": 3,
"flavor": "vanilla",
"price": "150",
"taste": "super",
"cream": "high",
"investments": null,
},
{
"id": 8,
"flavor": "chocolate",
"price": "250",
"taste": "super high",
"cream": "fantastic",
"investments": "too high",
}
...
]
Please do help me. I tried just by using label: type.flavor but nothing was displayed. And in order to make code effective i want to use the response coming from API call made in component A
use just have to add a variable at the place of option as shown below:
<template>
<div class="The V-select">
<vselect v-model="input1" :options="icecream" :dir="$vs.rtl ? 'rtl' : 'ltr'" />
</div>
</template>
<script>
import vselect from 'vue-select'
...
input1: null,
icecream: null
...
methods: {
forVselect (id) {
this.$http.get(`/type/${id}`)
.then((res) => {
this.icecream = res.data})
.catch((e) => {console.log(e)})
}
},
mounted (){
this.forVselect (this.$route.params.un_id)
}
</script>
and also you need modify your api response... response like:
[
{
"id": 3,
"flavor": "vanilla",
"price": "150",
"taste": "super",
"cream": "high",
"investments": null,
"label": "Vanilla" ,
"value": "vanilla"
},
{
"id": 8,
"flavor": "chocolate",
"price": "250",
"taste": "super high",
"cream": "fantastic",
"investments": "too high",
"label": "Chocolate" ,
"value": "chocolate"
}
...
]
you need to modify response like that from server side or client side when response received...
If you don't want to modify your json response so atleat you need to add 2 additional key which is label & value key so that you can use...
I tried to use :getOptionKey="getOptionKey" so I could change the default "id" vue-select was requesting but to me the only think that worked is to consider the object attribute "value" as the default.
So since I was working with array of objects being returned from API, what I did was:
// loading from API
dataUtils.find(this.$route.params.id).then((data) => {
this.mySelectObject = {
name: data.name,
value: data.id
}
and used the following within html:
<v-select
label="name"
:options="myOptions"
v-model="mySelectObject"
#input="setSelected" //created this method to change selection
/>
Here is an example of my JSON data :
"data":[
{
"id":01,
"name":"test",
"parent_id":null,
"children":[
{
"id":15,
"name":"subChild",
"parent_id":21,
"children":[
{
"id":148,
"name":"subSubChild",
"parent_id":22,
"children":[
....
]
}
]
}
]
},
I would like to filter this level by level. I have made this method :
computed: {
filteredData: function () {
let filterData = this.filter.toLowerCase()
return _.pickBy(this.data, (value, key) => {
return _.startsWith(value.name.toLowerCase(), filterData)
})
},
This work for only the first "level" and I tried several solutions but none worked for children.
So, I would like to be able to filter by several levels.
If you have an idea!
Thank you
A recursive function could come in handy for this particular purpose.
Try the following approach, and for better view, click on Full page link next to the Run code snippet button down below.
new Vue({
el: '#app',
data() {
return {
filter: '',
maintainStructure: false,
data: [{
"id": 01,
"name": "test",
"parent_id": null,
"children": [{
"id": 15,
"name": "subChild",
"parent_id": 21,
"children": [
{
"id": 148,
"name": "subSubChild",
"parent_id": 22,
"children": []
},
{
"id": 150,
"name": "subSubChild3",
"parent_id": 24,
"children": []
}
]
}]
}]
}
},
methods: {
$_find(items, predicate) {
let matches = [];
for (let item of items) {
if (predicate(item)) {
matches.push(item);
}
else if (item.children.length) {
let subMatches = this.$_find(item.children, predicate);
if (subMatches.length) {
if (this.maintainStructure) {
matches.push({
...item,
children: subMatches
});
}
else {
matches.push(subMatches);
}
}
}
}
return matches;
},
filterBy(item) {
return item.name.toLowerCase().startsWith(this.filter.toLowerCase());
}
},
computed: {
filteredData() {
return this.$_find(this.data, this.filterBy);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<label>Filter by <code>item.name</code>:</label>
<input v-model.trim="filter" placeholder="e.g. subsub" />
</div>
<div>
<label>
<input type="checkbox" v-model="maintainStructure" /> Maintain structure
</label>
</div>
<hr />
<pre>{{filteredData}}</pre>
</div>
Note that I'm prefixing the function with $_ to sort of mark it as private function (as recommended in this Style Guide) since we're not going to invoke it anywhere else.
I've been messing with this for like 2 days and I just don't get it how to make KendoUI's Grid work with Durandal ie what has to be in the view and what in the viewmodel. I need to fetch the data from a service via Web API but I haven't even got it rendering.
Can anybody please help?
What I did this far:
Viewmodel:
function viewAttached(view) {
var vw = $(view),
grid = $('#pgGrid', vw);
var sampledata = [
{ "ID": 1, "firstName": 'Andrew', "lastName": 'Test' },
{ "ID": 2, "firstName": 'Aidi', "lastName": 'Test' },
{ "ID": 3, "firstName": 'Aiko', "lastName": 'Test' }
];
var pgtemplate = kendo.template($('#pgtemplate', vw).html());
var dataSource = new kendo.data.DataSource({
data: sampledata,
change: function () { // subscribe to the CHANGE event of the data source
$("#pgGrid tbody").html(kendo.render(pgtemplate, this.view())); // populate the table
}
});
dataSource.read();
grid.kendoGrid({
columns: [
{ title: 'ID', field: 'id', width: 40, template: pgtemplate },
{ title: 'First name', field: 'firstName', width: 40, template: pgtemplate },
{ title: 'Last name', field: 'lastName', width: 40, template: pgtemplate }
],
dataSource: dataSource,
editable: false,
pageable: {
refresh: true,
previousNext: false,
numeric: false
},
scrollable: {
virtual: true
},
sortable: false
});
}
And the view:
<div id="pgGrid"
data-kendo-role="grid"
data-kendo-bind="source: gridSource"
data-kendo-editable="true"
data-kendo-columns='["ID",
{ "field": "firstName", "width": "150px" },
{ "field": "lastName", "width": "100px" }]'
data-kendo-pageable="true">
</div>
<script id="pgtemplate" type="text/x-kendo-template">
<tr>
<td>#= id #</td>
<td>#= firstName #</td>
<td>#= lastName #</td>
</tr>
</script>
And I also have set up kendo binding in main.js:
kendo.ns = 'kendo-';
binder.beforeBind = function (obj, view) { kendo.bind(view, obj.viewModel); };
Can anyone please help
Andrew.
Since you are trying to use kendo mvvm to bind the kendo grid (kendo.ns = 'kendo-') you don't have to use jquery to select the grid and render it( grid.kendoGrid({ ) . In your view model just make a property call gridDatasource,
define(function (require) {
return {
gridDatasource:function(){
var sampledata = [
{ "ID": 1, "firstName": 'Andrew', "lastName": 'Test' },
{ "ID": 2, "firstName": 'Aidi', "lastName": 'Test' },
{ "ID": 3, "firstName": 'Aiko', "lastName": 'Test' }
];
var dataSource = new kendo.data.DataSource({
data: sampledata,
change: function () { // subscribe to the CHANGE event of the data source
$("#pgGrid tbody").html(kendo.render(pgtemplate, this.view())); // populate the table
}
});
return dataSource;
}
}
});
And just remove the viewAttached function you don't have to define grid in javascript again since you have defined it in the HTML.
And you can give the row template like this,
<div id="pgGrid"
data-kendo-role="grid"
data-kendo-bind="source: gridSource"
data-kendo-editable="true"
data-kendo-columns='["ID",
{ "field": "firstName", "width": "150px" },
{ "field": "lastName", "width": "100px" }]'
data-kendo-pageable="true"
data-kendo-rowTemplate="pgtemplate"
>
</div>
Knockout Kendo library simplifies this , have a look at this link , also if you use knockout external template you can define the rowTemplate in external file and load it dynamically. Refer this answer about fix for knockout external template when used with durandal
I want to load data from a JSON file into a panel (not a grid, just a panel) and display the info using a template. I am at a loss for how to hook up a panel with a model/store. I am using Sencha Architect if that matters. I have the store and model set up and connected. I'm just missing how to pass that info along to the panel itself.
The json file is like so:
"overview": {
"image": "my-picture.jpg",
"name": "my name",
"title": "my title",
"address": {
"line1": "123 Fake St",
"line2": "",
"city": "Nowhere",
"state": "NJ",
"zip" : "12345"
}
}
And the template I'd like to use would look like this:
<div>
<img src="images/{image}"><br/>
{name}, {title}
<br/>
{address.line1}<br/>
{address.line2}<br/>
{address.city}, {address.state}<br/>
{address.zip}
</div>
I have come up with an adequate solution:
...
// panel declaration in the items array
{
xtype: 'panel',
flex: 1,
region: 'west',
tpl: [
'<div>',
'<img src="images/{image}"><br/>',
'{name}, {title}',
'<br/>',
'{address.line1}<br/>',
'{address.line2}<br/>',
'{address.city}, {address.state}<br/>',
'{address.zip}',
'</div>'
],
width: 150,
bodyCls: 'x-panel-body-white',
header: false,
title: 'Address',
listeners: {
afterrender: {
fn: me.onPanelAfterRender,
scope: me
}
}
},
...
// and later on in the code, a function that fires after render
onPanelAfterRender: function(abstractcomponent, options) {
var s = Ext.getStore('MyAddresses');
var r = s.getAt(0).raw;
abstractcomponent.tpl.overwrite(abstractcomponent.body, r);
},