Kendo Grid rowTemplate JS function - javascript

In a single javascript file I have the following kendo grid option.
var relatedJobsGridOptions = ko.observable({});
//I am seeing message, javascript function is never used :(
function getName(name) {
return name;
}
relatedJobsGridOptions({
columns: [
{ field: 'name', title: 'Customer Name ', width: '160px' },
],
dataSource: OccData,
rowTemplate: (
'<tr style="background-color: rgb(246,246,246)" data-uid="#= uid #">' +
'<td>#=getName(name)# </td>' +
'</tr>'
),
overflow: false
});
How I can call the javascript function inside this rowTemplate?
I have referred few telerik forums, but as for as I searched none is matching my condition (My poor research :( I am completely got stuck here..)
Any suggestion would be helpful to me.

Just use a string interpolation:
function getName (name) {
return `<strong>${name}</strong>`
}
const rowTemplate = `
<tr style="background-color: rgb(246,246,246)" data-uid="#= uid #">
<td>#= ${ getName('some name') } #</td>
</tr>
`.trim()
console.log(rowTemplate);

Related

Kendo Grid: Column Template Click event throwing Uncaught SyntaxError: missing ) after argument list?

I am having a kendo grid with a column template click event. But on clicking the cell it is throwing the following error.
Uncaught SyntaxError: missing ) after argument list
following is my column template.
columns: [
{
field: 'name',
title: 'Industry',
headerTemplate: '<span>Industry</span><br><span style="font-size: 10px; font-weight: 400;">2-digit Code</span>',
width: '40%',
template: '<div style="text-decoration: underline" onClick=\'logElement(#= name #)\'>#= name#</div>'
//template: function (dataItem) {
// return '<span style="text-decoration: underline">' + dataItem.name + '</span>';
//}
}
Google search saying it may be syntax error, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Missing_parenthesis_after_argument_list
But I could not found what I haven't escaped in the above template.
Can anyone please help me out?
Google's right: It is a syntax error. You are trying to submit a name to the function logElement. Let me guess: name is a string? In this case you have to put the value into quotes. This should work:
columns: [
{
field: 'name',
title: 'Industry',
headerTemplate: '<span>Industry</span><br><span style="font-size: 10px; font-weight: 400;">2-digit Code</span>',
width: '40%',
template: '<div style="text-decoration: underline" onClick="logElement(\\"#= name #\\")">#= name#</div>'
//template: function (dataItem) {
// return '<span style="text-decoration: underline">' + dataItem.name + '</span>';
//}
}

Angular-UI grid : adding custom field in columnDefs and access it from header template

I want to add some custom field in columnDefs and want to access it from header template.
As an example , i want a field let say showFile
$scope.gridOptions.columnDefs = [
{
name: 'ServiceID',
displayName: 'Service',
showFile: some data
}]
and want to access showFile inside header template ...
<div class="ui-grid-top-panel" style="text-align: center">
{{ want to access 'showFile' }}
</div>
What's the best possible way to do this. As i have tried it using custom method as
<div class="ui-grid-top-panel" style="text-align: center">
{{grid.appScope.letter()}}
</div>
(plnkr link http://plnkr.co/edit/ZW43LsiLY7GdnX6XEOgG?p=preview ,
http://plnkr.co/edit/3E8HTz4Z2daGqRh1WHtx?p=preview) but , the function (grid.appScope.letter()) is being called for infinite number of times . I have raised the issue but didn't got any reply .. https://github.com/angular-ui/ui-grid/issues/4250 , https://github.com/angular-ui/ui-grid/issues/4314. Can anyone please suggest the best possible way to achieve the above mentioned task.
Try using renderIndex. This will give you the column's index.
{{grid.appScope.gridOptions.columnDefs[renderIndex].customField}}
To access showFile in there, have you tried...
{{grid.appScope.gridOptions.columnDefs[0].showFile}}
I edited the plnkr: http://plnkr.co/edit/kdU59pZYQT0B76vYBQC8?p=preview.
I'm not sure if that's what you want to do, i used the headerCellTemplate in the columnDefs object instead of the headerTemplate, then you access with: {{col.colDef.showFile}}
columnDefs: [{
field: 'name',
displayName: 'First Name',
width: 90
}, {
field: 'title',
displayName: 'Last Name',
width: 80
}, {
field: 'test',
displayName: 'test',
width: 80,
showFile: 'FILE',
headerCellTemplate: '<div ng-class="{ \'sortable\': sortable }">' +
'<div class="ui-grid-cell-contents" col-index="renderIndex" title="TOOLTIP">' +
'<span>{{ col.displayName CUSTOM_FILTERS }}</span><br /><span>{{col.colDef.showFile}}</span>' +
'<span ui-grid-visible="col.sort.direction" ng-class="{ \'ui-grid-icon-up-dir\': col.sort.direction == asc, \'ui-grid-icon-down-dir\': col.sort.direction == desc, \'ui-grid-icon-blank\': !col.sort.direction }">' +
' ' +
'</span>' +
'</div>' +
'<div class="ui-grid-column-menu-button" ng-if="grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false" ng-click="toggleMenu($event)" ng-class="{\'ui-grid-column-menu-button-last-col\': isLastCol}">' +
'<i class="ui-grid-icon-angle-down"> </i>' +
'</div>' +
'<div ui-grid-filter></div>' +
'</div>'
}

ng-grid complete manipulation of the field

hi guys i have a couple of questions about ng-grid,
this is my grid-options
$scope.gridOptions= {
data:'data',
selectedItems:sel,
multiSelect:false,
columnDefs: [{ field: 'field1', displayName: 'field1',cellTemplate: template, cellClass:'cellToolTip'},
{field:'field2', cellTemplate: template, visible:false},
{ field:'field3', displayName:'field3', cellTemplate: template, cellClass:'cellToolTip' },
{ field: 'field4', displayName: 'field4',cellTemplate: templatetest} ,
{ field: 'dataInserimento', displayName: 'Data richiesta',cellTemplate: template, cellClass:'cellToolTip'} ,
{ displayName: 'field5', cellTemplate:'<div ><button ng-diasbled="pdfenabled" ng-click="reportpdf()"><i class="glyphicon glyphicon-file"></i></button></div>', cellClass:'gridCell' }]
}
}
and the two possible cell template are these
var template = '<div class="ngCellText" ng-class="col.colIndex()"><a id="gridField" ng-cell-text>{{row.getProperty(col.field)}}</a></div>';
var templatetest = '<div ng-disabled="enabled" class="ngCellText" ng-class="col.colIndex()"><a id="gridField" ng-cell-text>{{row.getProperty(col.field)}}</a></div>'
the data array is something similar to that one
[{field1:'something',
field2:'something',
field3:'something',
field4:[{otherstuff:'something',morestuff:'something'}],
field5:'something'}
{field1:'something',
field2:'something',
field3:'something',
field4:[{otherstuff:'something',morestuff:'something'}],
field5:'something'}
{field1:'something',
field2:'something',
field3:'something',
field4:[{otherstuff:'something',morestuff:'something'}],
field5:'something'}
}]
so the first problem is: how can i display the elements in the field4 field not like an array? is it possible to get only one or both values?
second question, it is possible to use a cell field property for another cell bind?
for example
if(field3==false){
$scope.enabled=true;
}
Write your template like this:
var templatetest = '<div ng-disabled="enabled" class="ngCellText" ng-class="col.colIndex()" ng-bind="row.getProperty(col.field)[0].otherstuff"></div>';
Look at this Plunker
Or even better you could use a filter:
app.filter('somefilter', function() {
return function(x) {
return x[0].otherstuff + ' / ' + x[0].morestuff;
};
});
in combination with this template:
var templatetest = '<div ng-disabled="enabled" class="ngCellText" ng-class="col.colIndex()" ng-bind="row.getProperty(col.field)|somefilter"></div>';
Look at this Plunker
Or (this includes the Answer to your second question) use row.entity to look up the full rowdata:
var templatetest = '<div ng-disabled="enabled" class="ngCellText" ng-class="col.colIndex()"> {{row.entity.field4[0].otherstuff+"/"+row.entity.field3}}</div>';
Here's the final Plunker
Hope you can get on with this.

apply formatting filter dynamically in a ng-repeat

My goal is to apply a formatting filter that is set as a property of the looped object.
Taking this array of objects:
[
{
"value": "test value with null formatter",
"formatter": null,
},
{
"value": "uppercase text",
"formatter": "uppercase",
},
{
"value": "2014-01-01",
"formatter": "date",
}
]
The template code i'm trying to write is this:
<div ng-repeat="row in list">
{{ row.value | row.formatter }}
</div>
And i'm expecting to see this result:
test value with null formatter
UPPERCASE TEXT
Jan 1, 2014
But maybe obviusly this code throws an error:
Unknown provider: row.formatterFilterProvider <- row.formatterFilter
I can't immagine how to parse the "formatter" parameter inside the {{ }}; can anyone help me?
See the plunkr http://plnkr.co/edit/YnCR123dRQRqm3owQLcs?p=preview
The | is an angular construct that finds a defined filter with that name and applies it to the value on the left. What I think you need to do is create a filter that takes a filter name as an argument, then calls the appropriate filter (fiddle) (adapted from M59's code):
HTML:
<div ng-repeat="row in list">
{{ row.value | picker:row.formatter }}
</div>
Javascript:
app.filter('picker', function($filter) {
return function(value, filterName) {
return $filter(filterName)(value);
};
});
Thanks to #karlgold's comment, here's a version that supports arguments. The first example uses the add filter directly to add numbers to an existing number and the second uses the useFilter filter to select the add filter by string and pass arguments to it (fiddle):
HTML:
<p>2 + 3 + 5 = {{ 2 | add:3:5 }}</p>
<p>7 + 9 + 11 = {{ 7 | useFilter:'add':9:11 }}</p>
Javascript:
app.filter('useFilter', function($filter) {
return function() {
var filterName = [].splice.call(arguments, 1, 1)[0];
return $filter(filterName).apply(null, arguments);
};
});
I like the concept behind these answers, but don't think they provide the most flexible possible solution.
What I really wanted to do and I'm sure some readers will feel the same, is to be able to dynamically pass a filter expression, which would then evaluate and return the appropriate result.
So a single custom filter would be able to process all of the following:
{{ammount | picker:'currency:"$":0'}}
{{date | picker:'date:"yyyy-MM-dd HH:mm:ss Z"'}}
{{name | picker:'salutation:"Hello"'}} //Apply another custom filter
I came up with the following piece of code, which utilizes the $interpolate service into my custom filter. See the jsfiddle:
Javascript
myApp.filter('picker', function($interpolate ){
return function(item,name){
var result = $interpolate('{{value | ' + arguments[1] + '}}');
return result({value:arguments[0]});
};
});
One way to make it work is to use a function for the binding and do the filtering within that function. This may not be the best approach: Live demo (click).
<div ng-repeat="row in list">
{{ foo(row.value, row.filter) }}
</div>
JavaScript:
$scope.list = [
{"value": "uppercase text", "filter": "uppercase"}
];
$scope.foo = function(value, filter) {
return $filter(filter)(value);
};
I had a slightly different need and so modified the above answer a bit (the $interpolate solution hits the same goal but is still limited):
angular.module("myApp").filter("meta", function($filter)
{
return function()
{
var filterName = [].splice.call(arguments, 1, 1)[0] || "filter";
var filter = filterName.split(":");
if (filter.length > 1)
{
filterName = filter[0];
for (var i = 1, k = filter.length; i < k; i++)
{
[].push.call(arguments, filter[i]);
}
}
return $filter(filterName).apply(null, arguments);
};
});
Usage:
<td ng-repeat="column in columns">{{ column.fakeData | meta:column.filter }}</td>
Data:
{
label:"Column head",
description:"The label used for a column",
filter:"percentage:2:true",
fakeData:-4.769796600014472
}
(percentage is a custom filter that builds off number)
Credit in this post to Jason Goemaat.
Here is how I used it.
$scope.table.columns = [{ name: "June 1 2015", filter: "date" },
{ name: "Name", filter: null },
] etc...
<td class="table-row" ng-repeat="column in table.columns">
{{ column.name | applyFilter:column.filter }}
</td>
app.filter('applyFilter', [ '$filter', function( $filter ) {
return function ( value, filterName ) {
if( !filterName ){ return value; } // In case no filter, as in NULL.
return $filter( filterName )( value );
};
}]);
I improved #Jason Goemaat's answer a bit by adding a check if the filter exists, and if not return the first argument by default:
.filter('useFilter', function ($filter, $injector) {
return function () {
var filterName = [].splice.call(arguments, 1, 1)[0];
return $injector.has(filterName + 'Filter') ? $filter(filterName).apply(null, arguments) : arguments[0];
};
});
The newer version of ng-table allows for dynamic table creation (ng-dynamic-table) based on a column configuration. Formatting a date field is as easy as adding the format to your field value in your columns array.
Given
{
"name": "Test code",
"dateInfo": {
"createDate": 1453480399313
"updateDate": 1453480399313
}
}
columns = [
{field: 'object.name', title: 'Name', sortable: 'name', filter: {name: 'text'}, show: true},
{field: "object.dateInfo.createDate | date :'MMM dd yyyy - HH:mm:ss a'", title: 'Create Date', sortable: 'object.dateInfo.createDate', show: true}
]
<table ng-table-dynamic="controller.ngTableObject with controller.columns" show-filter="true" class="table table-condensed table-bordered table-striped">
<tr ng-repeat="row in $data">
<td ng-repeat="column in $columns">{{ $eval(column.field, { object: row }) }}</td>
</tr>
</table>
I ended up doing something a bit more crude, but less involving:
HTML:
Use the ternary operator to check if there is a filter defined for the row:
ng-bind="::data {{row.filter ? '|' + row.filter : ''}}"
JS:
In the data array in Javascript add the filter:
, {
data: 10,
rowName: "Price",
months: [],
tooltip: "Price in DKK",
filter: "currency:undefined:0"
}, {
This is what I use (Angular Version 1.3.0-beta.8 accidental-haiku).
This filter allows you to use filters with or without filter options.
applyFilter will check if the filter exists in Angular, if the filter does not exist, then an error message with the filter name will be in the browser console like so...
The following filter does not exist: greenBananas
When using ng-repeat, some of the values will be undefined. applyFilter will handle these issues with a soft fail.
app.filter( 'applyFilter', ['$filter', '$injector', function($filter, $injector){
var filterError = "The following filter does not exist: ";
return function(value, filterName, options){
if(noFilterProvided(filterName)){ return value; }
if(filterDoesNotExistInAngular(filterName)){ console.error(filterError + "\"" + filterName + "\""); return value; }
return $filter(filterName)(value, applyOptions(options));
};
function noFilterProvided(filterName){
return !filterName || typeof filterName !== "string" || !filterName.trim();
}
function filterDoesNotExistInAngular(filterName){
return !$injector.has(filterName + "Filter");
}
function applyOptions(options){
if(!options){ return undefined; }
return options;
}
}]);
Then you use what ever filter you want, which may or may not have options.
// Where, item => { name: "Jello", filter: {name: "capitalize", options: null }};
<div ng-repeat="item in items">
{{ item.name | applyFilter:item.filter.name:item.filter.options }}
</div>
Or you could use with separate data structures when building a table.
// Where row => { color: "blue" };
// column => { name: "color", filter: { name: "capitalize", options: "whatever filter accepts"}};
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns">
{{ row[column.name] | applyFilter:column.filter.name:column.filter.options }}
</td>
</tr>
If you find that you require to pass in more specific values you can add more arguments like this...
// In applyFilter, replace this line
return function(value, filterName, options){
// with this line
return function(value, filterName, options, newData){
// and also replace this line
return $filter(filterName)(value, applyOptions(options));
// with this line
return $filter(filterName)(value, applyOptions(options), newData);
Then in your HTML perhaps your filter also requires a key from the row object
// Where row => { color: "blue", addThisToo: "My Favorite Color" };
// column => { name: "color", filter: { name: "capitalize", options: "whatever filter accepts"}};
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns">
{{ row[column.name] | applyFilter:column.filter.name:column.filter.options:row.addThisToo }}
</td>
</tr>

Extjs - Combo with Templates to Display Multiple Values

I am working on Extjs 4.1. I did implement an autocomplete feature for the text box. I'm now able to search for student's first or last name by entering a term, for example: Mat, and the result in text field would be:
Mathio,Jay << student's first and last name
Mark,Matt << student's first and last name
Then, I made some changes on the query so that i can get the subjects too when i search for one:
Mathio,Jay << student's first and last name
Mark,Matt << student's first and last name
Mathematics << subject
Here is my new query:
Query to search in multiple tables + Specify the returned value
Now, what i need is reconfigure the other parts so the field can display both cases, names and subjects
Here is my combo config:
,listConfig: {
loadingText: 'Loading...',
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<tpl if="l_name.length == 0"> ',
'<div class="x-boundlist-item">{f_name}<p><font size="1">Last Name: Unknown </font></p></div>',
'<tpl else>',
'<div class="x-boundlist-item">{f_name}<p><font size="1">{l_name}</font></p></div>',
'</tpl>',
'</tpl>'
),
and my model:
Ext.define("auto", {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
url: 'auto.php',
reader: {
type: 'json',
root: 'names',
autoLoad: true,
totalProperty: 'totalCount'
}
},
fields: ['f_name','l_name'
, {
name : 'display',
convert : function(v, rec) {
return rec.get('f_name') + ',' + rec.get('l_name');
}
}
]
});
I tried many times but still can't reach a good way to do it.
IMO you'd better use a simple model with only a 'name' field, and populate this field on the server-side. From your previous question, the server code would look like (in your query processing loop):
if (isset($row[2])) { // if the query returned a subject name in the row
$name = 'Subject: ' . $row[2];
} else if (isset($row[1])) { // if we have the last name
$name = 'Student: ' . $row[0] . ', ' . $row[1];
} else { // we have only the first name
$name = 'Student: ' . $row[0] . ' (Uknown last name)';
}
$names[] = array(
'name' => $name,
);
On the client-side, you would use a model with a single name field, and configure your combo box accordingly:
// Your simplified model
Ext.define('Post', {
extend: 'Ext.data.Model'
,fields: ['name']
,proxy: {
// Your proxy config...
}
});
Ext.widget('combo', {
displayField: 'name'
,valueField: 'name'
// Remaining of your combo config...
});
However, if you really want to mix students and subjects data in one single model, here are the modification you should do on your current code. First, you need to retrieve the subject name from the server. That means changing your server code to something like:
$names[] = array('f_name' => $row[0], 'l_name' => $row[1], 'subject' => $row[2]);
Then you need to add this field in your model on the client side, and adapt your display field's convert method to account for subject:
Ext.define('Post', {
extend: 'Ext.data.Model'
,fields: ['f_name', 'l_name',
'subject', // Add the subjet field to the model
{
name: 'display'
// Adjust your convert method
,convert: function(v, rec) {
var subject = rec.get('subject'),
lastName = rec.get('l_name'),
firstName = rec.get('f_name');
if (!Ext.isEmpty(subject)) {
return subject;
} else {
if (Ext.isEmpty(lastName)) {
return firstName + ' (Unknown last name)';
} else {
return firstName + ', ' + lastName;
}
}
}
}
]
,proxy: {
// Your proxy config...
}
});
Finally, since you already do that work in the display field of the model, you should use it as the displayField of the combo instead of doing it again in the combo's template.
E.g. combo config:
{
displayField: 'display'
,valueField: 'display'
// Remaining of your combo config...
}

Categories

Resources