Dynamically change kendo ui grid columns with AngularJS

The following HTML / JavaScript explains how to dynamically change Kendo UI grid columns, by using the Kendo – Angular directives.

 

<!doctype html> <html ng-app="researchApp"> <head> <meta charset="utf-8"> <title>Dynamically change Kendo grid columns.</title> <link href="/Client/Libraries/Kendo/css/kendo.common.min.css" rel="stylesheet" type="text/css" /> <link href="/Client/Libraries/Kendo/css/kendo.silver.min.css" rel="stylesheet" type="text/css" /> <script src="/Client/Libraries/Kendo/js/jquery.min.js"></script> <script src="/Client/Libraries/Angular/angular.js"></script> <script src="/Client/Libraries/Angular/angular-route.js"></script> <script src="/Client/Libraries/Angular/angular-sanitize.js"></script> <script src="/Client/Libraries/Kendo/js/kendo.all.min.js"></script> <script src="/Client/Libraries/Angular/angular-kendo.js"></script> <script src="/Client/Libraries/Q/q.min.js"></script> <script src="/Client/Libraries/Breeze/breeze.debug.js"></script> </head> <body ng-controller="researchCtrl"> <button ng-click="execute1($event)">Execute 1</button> <button ng-click="execute2($event)">Execute 2</button> <!-- By supplying the string "grid" to the kendo-grid directive, the kendo grid will be made available

to the $scope as $scope.grid. --> <!-- All initial configuration of the kendo grid is provided by the $scope.gridOptions. --> <!-- The kendo grid will "refresh" / "rebind" itself, when the $scope.selectedType changes. --> <div kendo-grid="grid" k-options="gridOptions" k-rebind="selectedType"></div> <script> // Main entry point of the application. // Kendo - Angular needs the ["kendo.directives"] to be injected. var researchApp = angular.module("researchApp", ["kendo.directives"]); researchApp.controller('researchCtrl', function ($scope) { var GridModel1 = kendo.data.Model.define({ id: 'Id', fields: { company: { type: 'string' }, os: { type: 'string' } } }); var GridModel2 = kendo.data.Model.define({ id: 'Id', fields: { FirstName: { type: 'string' }, LastName: { type: 'string' }, Description: { type: 'string' } } }); var gridOptions1 = { dataSource: new kendo.data.DataSource({ data: new kendo.data.ObservableArray([ new GridModel1({ Id: 1, company: 'Apple', os: 'OSX' }) ]), schema: { model: GridModel1 } }) }; var gridOptions2 = { dataSource: new kendo.data.DataSource({ data: new kendo.data.ObservableArray([ new GridModel2({ Id: 1, FirstName: 'John', LastName: 'Do', Description: "My test description." }) ]), schema: { model: GridModel2 } }) }; // Selected type is used to rebind the kendo ui grid. $scope.selectedType = ""; $scope.gridOptions = gridOptions1; $scope.execute1 = function (e) { // Switch $scope.gridOptions = gridOptions1; $scope.selectedType = "Software"; }; $scope.execute2 = function (e) { $scope.gridOptions = gridOptions2; $scope.selectedType = "Employee"; }; }); </script> </body> </html>

Initial screendump:

image

 

Screendump after clicking on the “Execute 2” button:

image

Dynamically call C# instance method by "string" name, without performance overhead.

 

There is no noticeable difference in calling a C# instance method directly or dynamically by "string" name, when you use a cached compiled LINQ expression.

 

In my test case I call a method 1.000.000 times directly and dynamically and both take 1,6s:

namespace Research.UnitTests
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.Reflection;
[TestClass]
public class Research
{
[TestMethod]
public void TestWithTiming()
{
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
var calculator = new Calculator();           
// Get "Calculate" method.
MethodInfo methodInfo = typeof(Calculator).GetMethod("Calculate", new Type[] { typeof(int) });
// Create parameter "i" for Calculate method.
ParameterExpression param = Expression.Parameter(typeof(int), "i");           
// Create "thisParameter" needed to call instance methods.
var thisParameter = Expression.Constant(calculator);
// Create an expression for the method call "Calculate" and specify its parameter(s).
// If the method was a static method, the "thisParameter" must be removed.
MethodCallExpression methodCall = Expression.Call(thisParameter, methodInfo, param);
// Create lambda expression from MethodCallExpression.
Expression<Func<int, string>> lambda = Expression.Lambda<Func<int, string>>(
methodCall,
new ParameterExpression[] { param }
);
// Compile lambda expression to a Func<>.
Func<int, string> func = lambda.Compile();
// Dynamically call instance method by "name".
// Duration: 1620 ms (1,6s).
for (int i = 0; i < 1000000; i++)
{
string result = func(i);
}
// Direct call
// Duration: 1605ms (1,6s)
for (int i = 0; i < 1000000; i++)
{
string result = calculator.Calculate(i);
}
watch.Stop();
System.Console.WriteLine(watch.Elapsed.TotalMilliseconds);
}
}
public class Calculator
{
public string Calculate(int i)
{
string result = string.Empty;
// Execute some code.
DateTime now = DateTime.Now;
DateTime nextDay = now.AddDays(i);
result = nextDay.ToString();
return result;
}
}
}

Fixing: TypeError: Cannot read property ‘sortable’ of undefined, when using Kendo UI grid.

I was getting the error: TypeError: Cannot read property ‘sortable’ of undefined.

This was caused by dynamically changing Kendo UI grid columns, without destroying the grid first.

After I destroyed the grid and recreated it, the error was resolved.

To destroy a Kendo UI grid and later recreate it, use:

 

// Destroy kendo UI grid.
// Must destroy and empty grid before refreshing columns.
$('#crudGrid').data().kendoGrid.destroy();
$('#crudGrid').empty();
// Create Kendo UI grid.
$('#crudGrid').kendoGrid({
dataSource: {
data: products,
schema: {
model: {
fields: {
ProductName: { type: "string" },
UnitPrice: { type: "number" },
UnitsInStock: { type: "number" },
Discontinued: { type: "boolean" }
}
}
},
pageSize: 20
},
height: 430,
scrollable: true,
sortable: true,
filterable: true,
pageable: {
input: true,
numeric: false
},
columns: [
"ProductName",
{ field: "UnitPrice", title: "Unit Price", format: "{0:c}", width: "130px" },
{ field: "UnitsInStock", title: "Units In Stock", width: "130px" },
{ field: "Discontinued", width: "130px" }
]
});

How to do a "Get latest version" in Visual Studio 2013 for a GitHub repository.

If you are connected to a GitHub repository from Microsoft Visual Studio 2013 (see: https://www.roelvanlisdonk.nl/?p=3773) and want to do a pull (= "Get latest version") from GitHub, just follow these steps:

1. Open Microsoft Visual Studio 2103

2. Open the Team Explorer.

3. Connect to Team project.

image

 

4. Choose the GitHub respository.

image

 

5. Once connected go to the "Unsynced Commits" tab.

image

 

6. Click on "Sync" or "Pull" button.

image

How to start working on a existing GitHub repository from Visual Studio 2013

If you are invited to work on a GitHub repository and you want to do so from Visual Studio 2013, then you can follow these steps:

 

Get the URL to the GitHub repository

Go to the repository on GitHub.com and copy the HTTPS clone URL or click on the copy to clipboard button:

image

 

 

Open Microsoft Visual Studio 2013.

Open the Team Explorer.

Click on the Clone button under "Local Git Repositries"

Enter the "clone url" from the GitHub page and enter a local folder, to store the code.

 

image

 

Open the code cloned and your good to go.

JavaScript private, public, shared and instance variables with IIFE.

Just a reminder, when using a Immediately-Invoked Function Expression (IIFE), you can create private, public, shared and instance variables:

<!DOCTYPE html>
<html>
<head>
<title>Show public - private - shared and instance variables.</title>
</head>
<body>
<script>
var Greeter = (function ()
{
var v1 = 10; // This is a private variable shared by all instances of Greeter.
function Greeter(name)
{
this.name = name;
this.v2 = 20; // This is a public instance variable.
var v3 = 30; // This is a private instance variable, can only be 
// accessed by the current Greeter instance.
} Greeter.prototype.v4 = 40; // This is a public variable shared by all instances of Greeter. Greeter.prototype.increase = function () { v1 = v1 + 1; this.v2 = this.v2 + 1; }; Greeter.prototype.logState = function () { console.log(this.name + ".v1 [" + v1.toString() + "]" +
this.name + ".v2 [" + this.v2.toString() + "]."); }; return Greeter; })(); var greeter1 = new Greeter("greeter1"); var greeter2 = new Greeter("greeter2"); greeter1.logState(); // Logs: greeter1.v1 [10] greeter1.v2 [20]. greeter2.logState(); // Logs: greeter1.v1 [10] greeter1.v2 [20]. greeter1.increase(); greeter1.logState(); // Logs: greeter1.v1 [11] greeter1.v2 [21]. greeter2.logState(); // Logs: greeter1.v1 [11] greeter1.v2 [20]. </script> </body> </html>

Automatic SQL Server query execution optimization: "get of my lawn"

 

I had to write a SQL query, that would return the records where the column "ImportFileName" started with the year "2013"

 

-- Drop temp table if it exists.
if object_id('tempdb..#Import') is not null
begin
drop table #Import
end
-- Create temp table.
create table #Import
(
Id int not null,
ImportFileName varchar (255) not null
)
-- Seed temp table.
insert into #Import (Id, ImportFileName) values 
(1, '20130506101010.csv'),
(2, '20130606101010.csv'),
(3, 'This_is_an_error_file.csv'),
(4, '20130806101010.csv'),
(5, '20130906101010.csv')
-- Query the temp table
select  Id
ImportFileName
from    #Import
where   datepart(year, cast(substring(ImportFileName, 1, 8) as date)) = 2013
-- Drop temp table.
drop table #Import

This query results in the error:

Msg 241, Level 16, State 1, Line 19
Conversion failed when converting date and/or time from character string.

This can be fixed with the SQL Server 2012 and above function: TRY_CONVERT:

-- The fixed query (>= SQL Server 2012)
select    Id
ImportFileName
from    #Import
where    datepart(year, try_convert(date, substring(ImportFileName, 1, 8))) = 2013

But in SQL Server 2008R2 this function does not exist, so I tried to trick SQL Server by using a subquery that would only return valid records:

-- Query the temp table
select  i.Id,
i.ImportFileName
from    (
select    Id,
ImportFileName
from    #Import
where    isdate(substring(ImportFileName, 1, 8)) = 1
) i
where   datepart(year, cast(substring(i.ImportFileName, 1, 8) as date)) = 2013

But this resulted in the same error, why????

Well the estimated execution plan tells you why:

image

 

image

 

Effectively SQL Server query optimization will merge the two where statements and convert the query above to something like:

 

select    Id,
ImportFileName
from    #Import
where    datepart(year, cast(substring(ImportFileName, 1, 8) as date)) = 2013
and     isdate(substring(ImportFileName, 1, 8)) = 1

which will fail.

 

To get around this problem, you could first insert the subquery records in a temp table and then check query the temp table, but in my case I used a case statement:

-- Query the temp table
select  i.Id,
i.ImportFileName
from    (
select    Id,
case    when isdate(substring(ImportFileName, 1, 8)) = 1
then    ImportFileName
else    null
end as ImportFileName
from    #Import
) i
where   datepart(year, cast(substring(i.ImportFileName, 1, 8) as date)) = 2013

The full script now look like:

-- Drop temp table if it exists.
if object_id('tempdb..#Import') is not null
begin
drop table #Import
end
-- Create temp table.
create table #Import
(
Id int not null,
ImportFileName varchar (255) not null
)
-- Seed temp table.
insert into #Import (Id, ImportFileName) values 
(1, '20130506101010.csv'),
(2, '20130606101010.csv'),
(3, 'This_is_an_error_file.csv'),
(4, '20130806101010.csv'),
(5, '20130906101010.csv')
-- Query the temp table
select  i.Id,
i.ImportFileName
from    (
select    Id,
case    when isdate(substring(ImportFileName, 1, 8)) = 1
then    ImportFileName
else    null
end as ImportFileName
from    #Import
) i
where   datepart(year, cast(substring(i.ImportFileName, 1, 8) as date)) = 2013
-- Drop temp table.
drop table #Import