Javascript inside Kendo Template is giving incorrect result - javascript

I have a template with javascript inside it
# if(IsSelected) { #
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: age"></td>
</tr>
# } #
It is intended to show only those records for which the IsSelected value is true. Though it shows only two records – the records displayed are not correct. What is the reason for this?
Fiddle: http://jsfiddle.net/Lijo/Z86dq/4/
CODE
<html>
<head>
<title>Template Filtering</title>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2013.2.716/js/kendo.all.min.js"></script>
<script id="row-template" type="text/x-kendo-template">
# if(IsSelected) { #
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: age"></td>
</tr>
# } #
</script>
<!--MVVM Wiring using Kendo Binding-->
<script type="text/javascript">
$(document).ready(function () {
kendo.bind($("body"), viewModel);
});
</script>
<script type="text/javascript">
var viewModel = kendo.observable({
employees: [
{ name: "Lijo", age: "28", IsSelected: true },
{ name: "Binu", age: "33", IsSelected: false },
{ name: "Kiran", age: "29", IsSelected: true }
]
});
</script>
<style>
table, th, td
{
border: 1px solid black;
}
</style>
</head>
<body>
<table id="resultTable">
<tbody data-template="row-template" data-bind="source: employees">
</tbody>
</table>
</body>
</html>

Try defining the template as:
<script id="row-template" type="text/x-kendo-template">
# if(IsSelected) { #
<tr>
<td>#= name #</td>
<td>#= age #</td>
</tr>
# } #
</script>
in order to avoid a double bind first in the tbody and then in the td.
EDIT: In order to avoid the problems with the error that throws KendoUI, I would change your code a little and instead of using a kendo.observable I would use a DataSource that implements filters.
So, you don't need to print or not the row in your template but setting the filter condition in the DataSource.
Define the template as follow:
<script id="row-template" type="text/x-kendo-template">
<tr>
<td>#= name #</td>
<td>#= age #</td>
</tr>
</script>
and your JavaScript code as:
var ds = new kendo.data.DataSource({
data : {
employees: [
{ name: "Lijo", age: "28", IsSelected: true },
{ name: "Binu", age: "33", IsSelected: false },
{ name: "Kiran", age: "29", IsSelected: true }
]
},
schema: {
data: "employees"
},
filter: { field: "IsSelected", operator: "eq", value: true }
});
Where I set a filter that filters out elements where isSelected is not equal to true.
Then initialize a ListView as follow:
$("#list").kendoListView({
dataSource: ds,
template : $("#row-template").html()
});
You can see the code here: http://jsfiddle.net/OnaBai/Z86dq/16/

This is my syntax, but this is coming from a sub grid. So I think the syntax you need may be a little different. I think //# just becomes # if it's in the parent Grid but don't quote me on it. Looks like your missing some " " and concatenation
Here's the razor syntax for what it's worth, maybe you can convert it to your needs
.Columns(columns =>
{
columns.Bound(x => x.FirstName).Title("First Name").ClientTemplate(
"# if (Id == 5) { #" +
("<a class href='javascript: void(0);' onclick=\"return MyFunction('#=LastName#', '#= FirstName #');\">Convert</a>") +
"# } else { #" +
"#= FirstName #" +
"# } #");
columns.Bound(x => x.LastName).Title("Last Name");
columns.Bound(x => x.Id).Title("User ID");
})
So this code reads as, If the Id of the user is 5, the column will have a hyperlink that says "convert" and will call MyFunction with those parameters. If not show the user's name

The problem comes from the fact that the MVVM implementation expects the template to render one element. In your case, you can use the visible binding - check an updated version of the fiddle.
<tr data-bind="visible: IsSelected">
<td data-bind="text: name"></td>
<td data-bind="text: age"></td>
</tr>

Related

How can I extend a table with backend data by columns instead of rows in Vue.js?

I have a table layout that currently looks like this:
This works well because I can place all my data for one row inside of my item object, and just render the TableRow object as <tr><td>...</td><td>...</td>....
One solution could be to subdivide my item object by column, and return only the corresponding value:
<tbody>
<tr v-for="(item, rowIndex) in store.selectedItems" :key="item.id">
<!-- iterate over each column within each row -->
<td v-for="(col, colIndex) in columns" :key="colIndex">
{{ item[col.field] }}
</td>
</tr>
</tbody>
However, ideally I would like to define the whole column in a single TableCol component instead of having to render the entire table like this. Is this somehow possible?
As per my understanding you want to create a separate shared component for column, So that you can reuse that anywhere by just passing a dynamic props. If Yes, Here you go :
Vue.component('tableCol', {
props: ['column', 'rowitem'],
template: `<td>{{ rowitem[column.field] }}</td>`
});
var app = new Vue({
el: '#app',
data: {
store: {
selectedItems: [{
id: 1,
name: 'Alpha',
age: 21
}, {
id: 2,
name: 'Beta',
age: 25
}, {
id: 3,
name: 'Gamma',
age: 30
}]
},
columns: [{
field: 'name'
}, {
field: 'age'
}]
}
});
table, tr, td {
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<tbody>
<tr v-for="item in store.selectedItems" :key="item.id">
<template>
<table-col v-for="(column, index) in columns" :column="column" :rowitem="item" :key="index"/>
</template>
</tr>
</tbody>
</table>
</div>

In my code i am tring to loop thorugh an object. Would this Vue js code be considered "AntiPattern"?

I'm new to Vue js and want to see if this proper coding practice. I am using v-for to loop through the objects but am not sure if this an antipattern. The first object is what i'd like to use to build the header colum. The next object(s) would be the item information. To clarify i am not sure if looping through an object this way is bad practice. I am looping through the first item to use the values as an index so that i can create rows for property in each object.
<thead>
<tr >
<th v-for="comparison in cartComparisons" class="flex-1 bg-gray-200 border-b border-white">
<a v-if="comparison.model.link" :href="comparison.model.link | ''">
{{comparison.model.name}}
</a>
<template v-else>{{comparison.model.name}}</template >
</th>
</tr>
</thead>
<tbody >
<template v-for='(comparison,key,index) in cartComparisons[0]'>
<tr v-if="index !== 0">
<td v-for="comparison in cartComparisons">
{{comparison[key]}}
</td>
</tr>
</template>
</tbody>
<script>
export default{
props:{
product: Object,
},
data () {
return {
cartComparisons: [
{
model: {
name: "Model",
},
price: 'Our Price',
frame: 'Frame',
frameTreatment: 'Frame Treatment',
loadCapacity: 'Load Capacity',
folding: 'Folding',
wheels: 'Wheels',
straps: 'Straps',
kickstand: 'Kickstand',
padding: 'Padding',
hardware: 'Hardware',
storageBag: 'Storage Bag',
},
{
model: {
name: "bike",
},
price: "$45.95",
frame: "Aluminum",
frameTreatment: "Treated",
loadCapacity: "65lbs",
folding: "Yes",
wheels: '7"',
straps: "3 Included",
kickstand: "Single Leg",
padding: "Rubber",
hardware: "Stainless Steel",
storageBag: "Bag included",
},
],
};
},
};
</script>

load json data in bootstrap data table

i created a table using html . now i want to populate my table using json data. i have been using the example https://www.youtube.com/watch?v=A20PY5RxdI8
my javascript code is here
$(document).ready(function () {
$.getJSON("my.php", function(json){
myjson = json;
}).done(function() {
$('#tble').bootstrapTable('load', myjson);
var $table = $('#tble');
$table.bootstrapTable('load', myjson);
$table.bootstrapTable({
search: true,
pagination: true,
buttonsClass: 'primaryt',
showFooter: true,
minimumCountColumns: 2,
columns: [ {
field: 'one',
title: 'ID'
}, {
field: 'two',
title: 'f name'
}, {
field: 'three',
title: 'last name'
}],
data: myjson
});
});
});
<table id = 'tble'>
<tr class=xl70 height=42 style='mso-height-source:userset;height:31.5pt'>
<th height=42 class=xl72 width=57 style='height:31.5pt;border-top:none;
border-left:none;width:43pt' data-field="one">1</th>
<th class=xl72 width=80 style='border-top:none;border-left:none;width:60pt'>2</th>
<th class=xl72 width=97 style='border-top:none;border-left:none;width:73pt'>3</th>
</tr>
</table>
i want to populate json into my table but it does not display any data in the said table
You can use the following code example:
$.getJSON("my.php")
.done(function(data) {
$('#tble').bootstrapTable('load', data);
})
Read the $.getJson() documentation for more example.
I have checked the documentation of Bootstrap table which you are using in your example.
The document is poorly written without explaining the parameters. Which results in confusion. When you read the document and do some JS fiddle you will realise that data-toggle attribute is very important. The value of this attribute should be the same as the Id of your table.
you can try removing data attribute filed in below fiddle to verify it.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://unpkg.com/bootstrap-table#1.15.3/dist/bootstrap-table.min.css" rel="stylesheet">
<script src="https://unpkg.com/bootstrap-table#1.15.3/dist/bootstrap-table.min.js"></script>
<div id="toolbar">
<button id="button" class="btn btn-secondary">load</button>
</div>
<table
id="table"
data-toggle="table"
data-height="460">
<thead>
<tr>
<th data-field="id">ID</th>
<th data-field="name">Item Name</th>
<th data-field="price">Item Price</th>
</tr>
</thead>
</table>
<script>
var $table = $('#table')
var $button = $('#button')
function randomData() {
var startId = ~~(Math.random() * 100)
var rows = []
for (var i = 0; i < 10; i++) {
rows.push({
id: startId + i,
name: 'test' + (startId + i),
price: '$' + (startId + i)
})
}
return rows
}
$(function() {
var someData = randomData();
debugger;
$table.bootstrapTable('load', someData)
})
</script>
You will need to modify your code as below.
HTML
<table id = 'tble' data-toggle="tble">
<thead>
<tr>
<th data-field="one">ID</th>
<th data-field="two">f name</th>
<th data-field="three">last name</th>
</tr>
</thead>
</table>
and JS
$(document).ready(function () {
$('#table').bootstrapTable({
url: 'my.php',
pagination: true,
search: true,
columns: [{
field: 'one',
title: 'ID'
}, {
field: 'two',
title: 'f name'
}, {
field: 'three',
title: 'last name'
}]
})
});
Note: your URL should return a json response. Else instead of getJSON you can use $.ajax

table in Angular using dynamic table headers

I was creating an angular app to display data from various data sources. I configured the list of various data sources in a JSON file each data source has a set of values attached to it.
Here is an example
var configurableConfigurations=[
{
name:"Locations",
table:"location_set",
columnList:[
{
name:"LOCATION_NAME",
alias:"Location",
primary:true
},
{
name:"DESCRIPTION",
alias:"Description",
primary:false
}
]
},
{
name:"System Parameters",
table:"system_params",
columnList:[
{
name:"param_Key",
alias:"Parameter",
primary:true
},
{
name:"param_Value",
alias:"Value",
primary:false
}
]
}
];
I then created an HTML page to display this using angular : the page has 2 parts
1. A select box which shows various parameters this is done using ng-repeat
<select name="ConfigurationName" ng-model="selected" ng-options="eachConfiguration.name for eachConfiguration in configurableConfigurations" ng-change="fetchRequiredConfiguration()">
A table which I want to generate using the headers of the parameter selected
this is my code to do that
<table id="configtable">
<thead>
<tr>
<th class="col-md-1" ng-repeat="column in selected.columnList" >{{column.alias}}</th>
</tr>
</thead>
This works great for the first time. But when the option is selected again using the select box the table header is not shown.
The table data is being populated properly , its just the table headers that are getting messed up.
Could anyone please help me get around this problem. I am new to angularjs. May be I am missing something important.
Edit ::
I should Also Mention that I fetch the data from the API and then was using the Data table plugin(https://www.datatables.net/download/) to show this as Data
$("#configtable").DataTable({
"ajax": "../fetchvalue/config/"+this.selected.table,
destroy: true,
"columns":{ "data": "ColumnXXX"},
{"data": "ColumnYYY" }
});
As it turns out, I have a problem with the disappearing headers only when I use the DataTable
I don't know how the table data is store but this way is good:
$scope.configurableConfigurations = [{
name: "Locations",
table: "location_set",
columnList: [{
name: "LOCATION_NAME",
alias: "Location",
primary: true
}, {
name: "DESCRIPTION",
alias: "Description",
primary: false
}],
data:[[12,"home"],[43,"work"]]
}, {
name: "System Parameters",
table: "system_params",
columnList: [{
name: "param_Key",
alias: "Parameter",
primary: true
}, {
name: "param_Value",
alias: "Value",
primary: false
}],
data:[["GOO",586],["FOO",123]]
}];
And then you can print the table like this:
<select name="ConfigurationName" ng-model="selected" ng-options="eachConfiguration as eachConfiguration.name for eachConfiguration in configurableConfigurations" ng-change="fetchRequiredConfiguration()"></select>
<table id="configtable">
<thead>
<tr>
<th class="col-md-1" ng-repeat="column in selected.columnList">{{column.alias}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in selected.data" >
<td class="col-md-1" ng-repeat="col in row">{{col}}</td>
</tr>
</tbody>
</table>
Example here

Generate table body rows using ng-repeat

I'm using Smart Table (latest version) and AngularJs (v. 1.2.16) to build a table using two objects, one for the header and the other for the table content. My problem happens when creating the table body cells. Using the following code works fine:
<tr ng-repeat="row in rowCollection">
<td>{{row.productNumber}}</td>
<td>{{row.BuyIt}}</td>
<td>{{row.brand}}</td>
</tr>
But I need to generate the body like this:
<tr ng-repeat="row in rowCollection">
<td ng-repeat="col in columns">{{value-to-show}}</td>
</tr>
My object is this:
$scope.rowCollection = [{
"productNumber": 5877,
"BuyIt": "Online",
"brand": "BrandA"
}, {
"productNumber": 5743,
"BuyIt": "Online",
"brand": "BrandB"
}];
$scope.columns = [{
'colName': 'Product Number',
'Id': 'column1',
'className': '',
'skipNatural': true,
'sortDefault': 'reverse'
}, {
'colName': 'Store or Online',
'Id': 'column2',
'className': '',
'skipNatural': true
}, {
'colName': 'Brand',
'Id': 'column3',
'className': '',
'skipNatural': true
}];
How can I get the right value to appear in the right cell?
I have a jsfiddle that shows the problem: http://plnkr.co/edit/aEfzzU?p=preview
Any help is really appreciated.
You can change your ng-repeat to this:
<tbody>
<tr ng-repeat="row in rowCollection">
<td ng-repeat="(key, value) in row">{{value}}</td>
</tr>
</tbody>
You may also extend your column objects with which property it corresponds with like this:
<tr ng-repeat="row in rowCollection">
<td ng-repeat="col in columns">{{row[col.property]}}</td>
</tr>
This will also have the nice side effects of:
You may in your header use the st-sort directive on col.property to enable sorting
Dynamically change which columns to display
Use your column objects as a configuration for both header and body
Use on complex objects which contains more properties than you care to show!

Categories

Resources