An angularjs switch / toggle, that works in IE8 and modern browser will get css 3 transitions.

Code can be found at: http://plnkr.co/edit/wBFKg33JxG7ABIHBvtik?p=preview

 

image

 

 

 

image

 

Based on the code found at: http://codepen.io/iamtyce/pen/kxrhC

 

html template

<div class="toggle toggle-alternate {{ value }}">
<label class="{{ value }}">{{ getSwitchText() }}</label>
<input ng-class="{ isChecked: value == 'off' }" type="radio" name="toggle" value="off" ng-model="value">
<input ng-class="{ isChecked: value == 'on' }" type="radio" name="toggle" value="on" ng-model="value">
<span class="switch {{ value }}"></span>
</div>

Part of the code

image

How to refresh a kendo ui widget, when options on the AngularJS $scope change.

Code can be found at: http://plnkr.co/edit/8CQURTLHftIpBwXUAN7s?p=preview

 

Let say, we want to show all records in a pageable kendo-grid, when the user clicks on a button.

This can accomplished by programmatically setting the page size of a kendo-grid and using the k-rebind attribute:

 

image

 

After clicking on the “Set page size” button:

 

image

 

<!-- App scripts -->
<script>
(function () {
"use strict";
// This is the starting point (main) for the angular app.
var app = angular.module("spike", ["kendo.directives"]);
// Set culture info to Ducth:
kendo.culture("nl-NL");
}());

(function () {
"use strict";
var app = angular.module("spike");
var controller = function ($scope, $animate) {
$scope.title = "Programmatically set pagesize kendo grid.";
var data = [
{ id: 1, name: "Bob1" },
{ id: 2, name: "Bob2" },
{ id: 3, name: "Bob3" },
{ id: 4, name: "Bob4" },
{ id: 5, name: "Bob5" },
{ id: 6, name: "Bob6" },
{ id: 7, name: "Bob7" },
{ id: 8, name: "Bob8" },
{ id: 9, name: "Bob9" },
{ id: 10, name: "Bob10" },
{ id: 11, name: "Bob11" },
{ id: 12, name: "Bob12" }
]
$scope.mainGridOptions = {
dataSource: {
data: data,
pageSize: 4
},
pageable: {
pageSizes: [4, 8, 12]
},
sortable: true,
dataBinding: function (e) {
// This is a fix.
// When the user selects an other page size in the "page size" dropdownlist, 
// the MainGridOptions are not updated.
// To reflect the changes from the "page size" dropdownlist, we set the "page size" manually here.
$scope.mainGridOptions.dataSource.pageSize = e.sender.dataSource.pageSize();
}
};
$scope.setPageSize = function () {
$scope.mainGridOptions.dataSource.pageSize = data.length;
};
};
app.controller("main", ["$scope", controller]);
}());
</script>
<div ng-controller="main">
<h2>{{ title }}</h2>
<div>
<br />
<button ng-click="setPageSize()">Set page size</button>
<br />
<br />
<div kendo-grid="mainGrid"
k-options="mainGridOptions"
k-rebind="mainGridOptions"></div>
</div>
</div>

Start progress animation (infinite rotate / spin) on click, without using angulars animation service ($animate).

 

See code at, Plunker: http://plnkr.co/edit/jUzCC1FmtgxdX4gWTVIW?p=preview

 

I used a custom directive with isolated scope:

<!-- App scripts -->
<script>
(function () {
"use strict";
// This is the starting point (main) for the angular app.
var app = angular.module("spike", []);

}());
(function () {
"use strict";
// Adds an animation to an element.
var directive = function () {
function link($scope, element, attributes, controller) {
$scope.$watch('loading', function (newValue, oldValue) {
if (newValue === true) {
element.removeClass("progress-indicator fa fa-refresh spin");
element.addClass("progress-indicator fa fa-refresh spin");
}
else {
element.removeClass("progress-indicator fa fa-refresh spin");
}
});   
}
return {
restrict: "EA",  // Directive be used as element and as attribute.
link: link,
scope: {
// This directive expects an attribute "loading".
// The value of the attribute "loading" will be watched.
// When this value === true, classes will be added to "show" and animate a progressindicator.
// When this value !== true, classes will be removed, to stop animation and "hide" the progressindicator.
loading: "=loading"
}
};
};
angular.module('spike').directive('zvdzProgress', [directive]);
}());
(function () {
"use strict";
var app = angular.module("spike");
var controller = function ($scope, $animate) {
$scope.title = "Start progress animation on click.";
$scope.isLoading = false;
$scope.start = function () {
$scope.isLoading = true;
};
$scope.stop = function () {
$scope.isLoading = false;
};
};
app.controller("main", ["$scope", controller]);
}());
</script>

 

<div ng-controller="main">
<h2>{{ title }}</h2>
<div>
<br />
<button ng-click="start()">Start</button>
<br />
<br />
<button ng-click="stop()">Stop</button>
<br />
<br />
<div zvdz-progress loading="isLoading"></div>
</div>
</div>

 

 

image

 

On start ng-click, a refresh icon is shown that spins:

image

Fix: wait cursor hang with AngularJS Block UI

When I stopped Block UI the wait cursor remained until I moved the mouse.

To fix this problem I changed the Block UI css (I moved the “cursor: wait” from the class .block-ui-container to the class .block-ui-active):

 

.block-ui-container {
position: absolute;
z-index: 10000;
top: 0; right: 0; bottom: 0; left: 0;
height: 0;
overflow: hidden;
opacity: 0;
filter: alpha(opacity=00);
}
.block-ui-active {
cursor: wait;
}

Add animation on dom event, by using a custom directive, the AngularJS $animate service and the Animate.css library.

image

 

Here’s is the code:

 

http://plnkr.co/edit/EdHyzxwLTfNRXFHj9iU1?p=preview

 

Yes, yes I know this can easily be done with the standard AngularJS ngAnimate directive, but I wanted to play around with a custom directive, isolated scope and the AngularJS $animate service. So I decided to use a wobble effect from the Animate.css library on a “alarm bell”.

 

The code use a css class “myWobble”, that uses a named keyframe animation from the Animate.css library, called: “wobble”.

.myWobble {
-moz-animation: wobble 1s;
-o-animation: wobble 1s;
-webkit-animation: wobble 1s;
animation: wobble 1s;
-webkit-animation-fill-mode: both;
-o-animation-fill-mode: both;
animation-fill-mode: both;
}

Then the custom directive “zvdz-animate” is used to start the animation on a dom event (in this case the on  “click” event). The directive will add the class “myWobble” to the element, when the animation is done and the “reset” option is set to “true”, the class “myWobble” will be removed, so when the user clicks again on the element, the animation is started again. When the “reset” option is set to “false” the class will not be removed and the animation will not be fired again.

In some case this is what you want, but in this case not.

<div class="alarmContainer" zvdz-animate="{ effects: [{ on: 'click', className: 'myWobble', reset: true }] }">
<a href="" class="fa fa-bell-o"></a>
</div>

How to sort items in a list with ng-repeat

Just a nice example on how to sort items in a list with ng-repeat:

http://plnkr.co/edit/qa6LdhDdggApWPmOrwGD?p=preview

<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="spike">
<head>
<!--
This page can be used as a base for spiking with jQuery, AngularJS and Kendo.
All scripts and styles are loaded from a CDN or inline.
-->
<title>Spike page</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- Use highest support for modern standards . -->
<!-- Library styles -->

<!-- Library scripts -->
    <script src="http://cdn.kendostatic.com/2014.2.1008/js/angular.min.js"></script>

<!-- App styles -->
<style>
/*
A small custom reset stylesheet is used, to fix style differences between browsers.
*/
html, body {
height: 100%; /* App layout uses a 100% height layout. */
}
body, div, p, ul, li {
border: 0; /* Remove unwanted space. */
-webkit-box-sizing: border-box; /* Place the border and padding inside the box. */
-moz-box-sizing: border-box; /* Place the border and padding inside the box. */
-ms-box-sizing: border-box; /* Place the border and padding inside the box. */
-o-box-sizing: border-box; /* Place the border and padding inside the box. */
box-sizing: border-box; /* Place the border and padding inside the box. */
margin: 0; /* Remove unwanted space. */
outline: 0; /* Remove unwanted space. */
padding: 0; /* Remove unwanted space. */
}
body {
padding: 20px; /* Create space between browser border and content. */
min-width: 320px; /* App will not work beneath width: 320px. */
}
</style>
<!-- App scripts -->
<script>
(function () {
"use strict";
// This is the starting point (main) for the angular app.
var app = angular.module("spike", ["kendo.directives"]);
}());
(function () {
"use strict";
var app = angular.module("spike");
var controller = function ($scope, service) {
$scope.title = "Sort items in a list.";
$scope.countriesAndCities = [
{ "id": 1, "name": "The Netherlands", "show": true, "sort": 1 },
{ "id": 2, "name": "Amsterdam", "show": true, "sort": 2 },
{ "id": 3, "name": "Rotterdam", "show": false, "sort": 3 },
{ "id": 4, "name": "US", "show": false, "sort": 4 },
{ "id": 5, "name": "Las Vegas", "show": true, "sort": 5 },
{ "id": 6, "name": "New York", "show": true, "sort": 6 }
];
};
app.controller("main", ["$scope", controller]);
}());
</script>
</head>
<body>
<div ng-controller="main">
<h2>{{ title }}</h2>
<div>
<br />
Normal order:
<br />
<br />
<div ng-repeat="item in countriesAndCities | filter: { show: true } | orderBy:'sort':true">
{{ item.name }}
</div>
<br />
<br />
Reversed order:
<br />
<br />
<div ng-repeat="item in countriesAndCities | filter: { show: true } | orderBy:'sort':false">
{{ item.name }}
</div>
</div>
</div>
</body>
</html>

Show hierarchy in combobox items, with Kendo and AngularJS.

Here is a plunkr showing a combobox with hierarchy:

http://plnkr.co/edit/PaiRPD6dZNq0JaT2Tkdg?p=preview

 

image

 

<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="spike">
<head>
<!--
This page can be used as a base for spiking with jQuery, AngularJS and Kendo.
All scripts and styles are loaded from a CDN or inline.
-->
<title>Spike page</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- Use highest support for modern standards . -->
<!-- Library styles -->
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.common.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.silver.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.silver.mobile.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.dataviz.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.dataviz.silver.min.css" rel="stylesheet" />
<!-- Library scripts -->
<script src="http://cdn.kendostatic.com/2014.2.1008/js/jquery.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.2.1008/js/angular.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.2.1008/js/kendo.all.min.js"></script>
<!-- App styles -->
<style>
/*
A small custom reset stylesheet is used, to fix style differences between browsers.
*/
html, body {
height: 100%; /* App layout uses a 100% height layout. */
}
body, div, p, ul, li {
border: 0; /* Remove unwanted space. */
-webkit-box-sizing: border-box; /* Place the border and padding inside the box. */
-moz-box-sizing: border-box; /* Place the border and padding inside the box. */
-ms-box-sizing: border-box; /* Place the border and padding inside the box. */
-o-box-sizing: border-box; /* Place the border and padding inside the box. */
box-sizing: border-box; /* Place the border and padding inside the box. */
margin: 0; /* Remove unwanted space. */
outline: 0; /* Remove unwanted space. */
padding: 0; /* Remove unwanted space. */
}
body {
padding: 20px; /* Create space between browser border and content. */
min-width: 320px; /* App will not work beneath width: 320px. */
}
.level1 {
}
.level2 {
padding-left: 30px;
}
</style>
<!-- App scripts -->
<script>
(function () {
"use strict";
// This is the starting point (main) for the angular app.
var app = angular.module("spike", ["kendo.directives"]);
}());
(function () {
"use strict";
var app = angular.module("spike");
var controller = function ($scope, service) {
$scope.title = "Show hierarchy in combobox items, with Kendo and AngularJS.";
$scope.countriesAndCities = [
{ "id": 1, "name": "The Netherlands", "level": 1 },
{ "id": 2, "name": "Amsterdam", "level": 2 },
{ "id": 3, "name": "Rotterdam", "level": 2 },
{ "id": 4, "name": "US", "level": 1 },
{ "id": 5, "name": "Las Vegas", "level": 2 },
{ "id": 6, "name": "New York", "level": 2 }
];
$scope.customTemplate = $("#customTemplate").html();
};
app.controller("main", ["$scope", controller]);
}());
</script>
</head>
<body>
<div ng-controller="main">
<h2>{{ title }}</h2>
<div>
<select kendo-combo-box
k-template="customTemplate"
k-placeholder="'Choose country'"
k-filter="contains"
k-data-source="countriesAndCities"
data-text-field="'name'"
data-value-field="'id'"
k-auto-bind="false"></select>
<script id="customTemplate" type="text/x-kendo-template">
<span class="k-state-default level#= level #">
#= name #
</span>
</script>
</div>
</div>
</body>
</html>

Using ValidateAntiForgeryToken with AngularJS and MVC

I was getting a HTTP 500 error, when posting data from AngularJS to a MVC controller, which had the attribute ValidateAntiForgeryToken applied to it. This attribute expects a form to be posted to the MVC controller action method, but I wanted to sent JSON. If you want to do that then you can follow the blogpost from julian jelfs.

 

Now I just add: @Html.AntiForgeryToken()

Then I apply the custom attribute ValidateJsonAntiForgeryToken to the MVC controller action method, like

[HttpPost]
[Authorize] [ValidateJsonAntiForgeryToken]
public ActionResult GetDashboardData(DashboardViewModel model) {

Now I can Post data in AngularJS like:

// When using the @Html.AntiForgeryToken() and [ValidateJsonAntiForgeryToken], a http POST, 
// should contain a AntiForgeryToken in the header. // The @Html.AntiForgeryToken() will write add a hidden HTML input element with the name
//"__RequestVerificationToken". // This input element will contain to AntiForgeryToken. // The MVC AuthorizeAttribute [ValidateJsonAntiForgeryToken],
//will check the http request header for the "AntiForgeryToken".
function getHttpConfig() { var token = angular.element("input[name='__RequestVerificationToken']").val(); var config = { headers: { '__RequestVerificationToken': token } }; return config; }

var config = getHttpConfig();
var url = “http://localhost”;
var postData = {}; return $http.post(url, postData, config).then(function (response) {
// Do something terrible
});

 

Solution

 

https://julianjelfs.wordpress.com/category/mvc/