Route Parameters – AngularJS

Hey everyone,

This is just a quick post on what I did to get my routes working properly with AngularJS. My routes looked like this:

//Configure routes
app.config(function ($routeProvider) {
    $routeProvider
		//...
        .when('/Businesses/Details/:id', {
            templateUrl: '/Businesses/Details'
        })
        //...
	.otherwise({
	    redirectTo: '/'
	});
});

And then to access the ID parameter I used $routeParams:


/* Used to display the lesson planner for customers */
app.controller("CustomerPlannerController", function ($scope, $routeParams /*, ... */) {
     console.log($routeParams);
     console.log($routeParams.id);
}

Using that setup, a route to /Businesses/Details/:id will display the following output in the console:

//Route to: /Businesses/Details/:id
Object {id: "1"} 
1

Note that you can call ID whatever you want, just make sure you change your route to match. Hopefully that’ll be enough to get you going, but if you have any issues check out these links:
http://stackoverflow.com/a/11064503/522859
http://docs.angularjs.org/api/ngRoute.$routeParams

TimeSelector / TimePicker Directive – AngularJS

Hey everyone,

I’ve been mucking around with directives for that last few days and one of my requirements has been a simple timepicker. Nothing too fancy, but if anyone would like to use it – feel free.

See the following fiddle for the demo: http://jsfiddle.net/LFB3F/2/

Timepicker Directive
Timepicker Directive

The directive is initialised with both the hour and minute defaults being set like this:


Note that hours and minutes should be set in the controller that wraps around the Timepicker:

app.controller("MyCtrl", function MyCtrl($scope) {
    $scope.hours = 11;
    $scope.minutes = 45;       
});

The hours and minutes will then be updated whenever the user changes the value. If you need any other hooks it’s fairly easy to modify and there are a heap of comments.

You may also want to put the HTML in an external template. Just make the following changes to the directive (note templateURL):

app.directive("ngTimeSelector", function () {
    return {
        restrict: 'EA',
        templateUrl: '/Directives/TimeSelector',
        scope: {
            hours: "=",
            minutes: "="
        },
        replace: true,
        link: function (scope, elem, attr) {
...
...

The JSFiddle is probably the easiest way to see how it all works. You can simply copy it from there to your app. Alternatively, I’ve dumped the code below:

Uncondensed HTML (for those who prefer to use a template)

{{displayHours()}}
{{displayMinutes()}}
= 12" class="display"> PM
<div ng-if="hours AM

Timepicker Directive

/* 
    http://www.whatibroke.com/?p=899
*/

var app = angular.module('myApp', []);

app.controller("MyCtrl", function MyCtrl($scope) {
    $scope.hours = 11;
    $scope.minutes = 45;       
});


app.directive("ngTimeSelector", function () {
    return {
        restrict: 'EA',
        template: '
{{displayHours()}}
{{displayMinutes()}}
= 12" class="display"> PM
<div ng-if="hours AM
', scope: { hours: "=", minutes: "=" }, replace: true, link: function (scope, elem, attr) { //Create vars scope.period = "AM"; /* Increases hours by one */ scope.increaseHours = function () { //Check whether hours have reached max if (scope.hours < 23) { scope.hours = ++scope.hours; } else { scope.hours = 0; } } /* Decreases hours by one */ scope.decreaseHours = function () { //Check whether hours have reached min scope.hours = scope.hours = 59) { scope.minutes = 0; } else { scope.minutes++; } } /* Decreases minutes by one */ scope.decreaseMinutes = function () { //Check whether to reset if (scope.minutes 12) { hoursToDisplay = scope.hours - 12; } //Check for 12 AM etc if (hoursToDisplay == 0) { //Set to am and display 12 hoursToDisplay = 12; } else { //Check whether to prepend 0 if (hoursToDisplay <= 9) { hoursToDisplay = "0" + hoursToDisplay; } } return hoursToDisplay; } /* Displays minutes */ scope.displayMinutes = function () { return scope.minutes = 12 ? scope.hours - 12 : scope.hours + 12; } } } });

Styles

body{
	background-color: #F0F0F0;
	font-family: "Lato", sans-serif;
	font-weight: 300;
	color: #363636;
}

.timeSelectorDirective {
    background: none;
    -webkit-user-select: none;      
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
}
.timeSelectorDirective .increase, .timeSelectorDirective .decrease{
    text-align: center;
    vertical-align: middle;    
    color: rgb(112, 112, 112);    
    text-shadow: 0px 1px #FFF;
    cursor: pointer;
    -webkit-transition: 500ms ease-out all;
    -moz-transition: 500ms ease-out all;
    -ms-transition: 500ms ease-out all;
    -o-transition: 500ms ease-out all;
    transition: 500ms ease-out all;
    font-size: 100%;
    border: 1px solid #CCC;
    padding: 3px;
    margin: 3px;
    border: 1px solid #EDE;
}

.timeSelectorDirective .increase:hover, .timeSelectorDirective .decrease:hover{
    color: rgba(112, 112, 112, 0.5);   
    border-color: #CCC;
    background-color: #FFF;
}

.timeSelectorDirective .increase:active, .timeSelectorDirective .decrease:active{
    color: rgb(112, 112, 112);
    box-shadow: inset 1px 1px 1px #DDD;
}

.timeSelectorDirective .section{
    display: inline-block;
}

.timeSelectorDirective .display{
    background-color: rgb(247, 247, 247);
    color: #555555;
    padding: 5px;
    margin: 0px 3px;
    min-width: 30px;
    text-align: center;
    border: 1px solid #DDD;
    box-shadow: 1px 1px 1px #FFFFFF;
}

Sample Usage

www.whatibroke.com

Hours: {{hours}}   Minutes: {{minutes}}

Misc Includes
AngularJS: http://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js
FontAwesome: http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css
Font: http://fonts.googleapis.com/css?family=Lato:300,300italic,400,700,700italic|Rokkitt:400,700.css

Passing Parameters from a Directive to a Function – AngularJS

Hey everyone,

This is just a quick post to help out anyone who runs into the same problems with directives that I did today. I was able to call the controllers function from the directive, however none of the parameters were being passed.

The issue ended up being that the parameters need to be named. For instance:

 
app.directive('ngPlanner', function () {
    return {
        restrict: 'EA',
        templateUrl: '/Businesses/PlannerDirective',
        scope: {
            lessons: "=",
            business: "=",
            lessonClicked: "&",
            addLesson: "&"
        },
        replace: true,
        link: function (scope, elem, attr) {
            var selectedIndex = null;

            console.log(scope);
            console.log(scope.lessons);
            scope.test = function (tester) {
                selectedIndex = tester;
                console.log("Directive: " + selectedIndex);
                scope.lessonClicked({ lesson: selectedIndex });
            }
        }
    }
});

/* Used for handling business details, planner, etc */
app.controller("BusinessDetailsController", function ($scope) {

    //Fired when the new lesson button is clicked in the planner directive
    $scope.newLesson = function (date) {
        console.log("New Lesson Clicked: " + date);
    }

    //Fired when a lesson is clicked on
    $scope.editLesson = function (lesson) {
        console.log("Lesson Clicked: " + lesson);
    }
});

Note particularly the scope.lessonClicked line. Instead of passing parameters normally, they should be named (scope.lessonClicked({lesson: selectedIndex}).

The naming should match that used in the HTML where your directive is added:
<ng-planner lessons=”plannerLessons” lesson-clicked=”editLesson(lesson)” add-lesson=”newLesson()” business=”true”></ng-planner>

A huge thanks to Jay B for posting the solution on the AngularJS groups page: https://groups.google.com/forum/#!topic/angular/3CHdR_THaNw

He’s also added the following JSFiddle: http://jsfiddle.net/simpulton/VJ94U/

And although pretty well hidden, it is actually mentioned in the documentation: http://docs.angularjs.org/guide/directive

Forcing a Link to Behave Normally – AngularJS

Hey everyone,

Another quick post. Working with AngularJS this morning I had a need for a link to redirect to a login page that was not contained within the “angular” part of the app. Unfortunately Angular was overriding the behavior and trying to route it.

The solution is fairly easy for this, simply add a target attribute:



Sign In


Sign In

There are a few other solutions depending on your use case, check out the following StackOverflow post for more info: http://stackoverflow.com/a/16838013/522859

JSON Issue: This request has been blocked because sensitive information – MVC

Hey everyone,

Started redoing Learner Lessons in MVC4 and AngularJS today. I ran into this little issue while trying to retrieve JSON:

This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet

It turns out that this behavious is intentionally prevented in order to avoid JSON hijacking. Thankfully the data I’m working with is not at all sensitive so the workaround is pretty straight forward:

public ActionResult Index()
{
     return Json(db.Regions.ToList(), JsonRequestBehavior.AllowGet);
}

Source: http://stackoverflow.com/a/4616442/522859

For those of you working with sensitive data that don’t want to risk exposing it, posting is suggested as an alternative on StackOverflow: http://stackoverflow.com/a/6440163/522859

ng-class with ng-repeat – AngularJS

Hey everyone,

Just another quick AngularJS post. This one is for using ng-class with ng-repeat. The goal here is to have a class applied to the non-selected elements. To start with, we’ll chuck the following in our controller:

$scope.transmission = {
selected: null,
options: [
{
name: 'Any'
},			
{	
name: 'Manual'
},			
{
name: 'Automatic'
}			
]
};

Here we’re just creating a few random objects. To keep things simple we’re going with transmission types: a manual car, automatic or any. Next you’ll want to add the markup:

...
{{option.name}}
...

Finally the class to be applied:

.line-through{
	text-decoration: line-through;
}

Creating a ‘Starts With’ Filter in AngularJs

Hey everyone,

Just a quick post on how to create a simply custom filter in AngularJS. We’ll be using the same regions objects as the other day:

{
	"regions": [
		{
			"id": "1",
			"postcode": "4700",
			"name": "Rockhampton",
			"description": "One of the major cities in Central Queensland."
		},
		{
			"id": "16",
			"postcode": "4214",
			"name": "Keppel Island",
			"description": "Awesome islands, very few people, heaps of fish beautiful clear water."
		}
	]
}

We’ll create the filter like so:

app.filter('regionsWithPostcode', function(){
	return function(regions, postcode){

		//Create vars
		var matching_regions = [];		

		//Check if input matches current postcode
		if(regions && postcode){		 	
		 	
		 	//Loop through each region
			for(var i = 0; i < regions.length; i++){
				if(regions[i].postcode.substr(0, postcode.length) == postcode){
					matching_regions.push(regions[i]);
				}
			}

			//Return matching regions
			return matching_regions;
		}
		else{
			return regions;
		}		
	}
});

And finally, we’ll setup the HTML as follows:

	
Use Postcode
{{region.name}}

Filter by Object Property in Ng-Repeat – AngularJS

Hey everyone,

Just a quick post on how to filter by a property when using ng-repeat. To start with, we’ll use the following objects:

{
	"regions": [
		{
			"id": "1",
			"postcode": "4700",
			"name": "Rockhampton",
			"description": "One of the major cities in Central Queensland."
		},
		{
			"id": "16",
			"postcode": "4214",
			"name": "Keppel Island",
			"description": "Awesome islands, very few people, heaps of fish beautiful clear water."
		}
	]
}

Then assuming you want to filter by the postcode all you need is the following:

Region

{{region.name}}

AngularJS ngAnimate Transitions – Basic Demo

Hey everyone,

I’ve just starting using Angular and went to do a few animations. I had a bit of trouble trying to find anywhere that mentioned what each class does. This is the demo we’ll be making, it’s pretty basic but hopefully enough to get you started: JSFiddle Demo

Dummy Page
To start with, just create a new page with the following. Note that none of the stuff below applies to the animation itself, this is just so that we’ve got something to work with.


	
		Test Animation
		
	
	
		
Add
{{person.name}}
//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js //Initialisation stuff, note that you don't need any of this for animations, just using it so there's something to see function PeopleController($scope){ $scope.name = ""; $scope.people = [ { name: "Santa Clause"}, { name: "Easter Bunny"}, { name: "Tooth Fairy"}, { name: "Chris Owens"}, { name: "Phillip Farnsworth"}, { name: "Clark Kent"}, { name: "Lana Lang"} ]; $scope.removePerson = function(row){ $scope.people.splice(row, 1); } $scope.addPerson = function(){ $scope.people.push({name: $scope.name}); $scope.name = ""; } }

Adding the ng-animate Directive
The first step to adding the transitions is to add the ng-animate directive:

{{person.name}}

Classes for Adding a New Element
Now we’re going to add the styles that are used when a new element is added to the page. To start with, you’ll want to create .person-enter. This is the class that will be animated from. In this instance we want new elements to start off invisible so we’ll set the opacity to 0.

.person-enter{
	-webkit-transition: 1s linear all;
	-moz-transition: 1s linear all;
	-ms-transition: 1s linear all;
	-o-transition: 1s linear all;
	transition: 1s linear all;
	opacity: 0;
}

Next we’ll want to add the styles for .person-enter.person-enter-active. These will be the styles that we want to animate to. Because we’re going from invisible to visible we’ll adjust the opacity:

.person-enter.person-enter-active{
	opacity: 1;
}

Classes for Removing an Element
Now we’ll add the class to animate from. This will the opposite of what we used when adding an element – start visible, go to invisble:

.person-leave{
	-webkit-transition: 1s linear all;
	-moz-transition: 1s linear all;
	-ms-transition: 1s linear all;
	-o-transition: 1s linear all;
	transition: 1s linear all;
	opacity: 1;
}

And finally the class to animate to when an element is removed:

.person-leave.person-leave-active{
	opacity: 0;
}

All Together Now
Finally we can put the whole thing together. The people boxes should now fade out and in whenever an element is added or removed. You can see it in action here: JSFiddle Demo


	
		Test Animation
		

		
			.person{
				padding: 20px;
				width: 50px;
				height: 50px;
				background-color: #E8FCE4;
				border: 1px solid #C0E2BB;
				float: left;
				margin: 5px;
				text-align: center;
				box-shadow: 2px 2px 2px #DAD3D3;
				text-shadow: 0px -1px 1px #FFF;
				cursor: pointer;
			}


			/*
				Note: you can condense these, however they've been split to make the explanation a little easier to follow;
			*/

			/* This is the class that will be animated *FROM* when a new person is added */
			.person-enter{
				-webkit-transition: 1s linear all;
				-moz-transition: 1s linear all;
				-ms-transition: 1s linear all;
				-o-transition: 1s linear all;
				transition: 1s linear all;
				opacity: 0;
			}

			/* This is the class that will be animated *TO* when a new person is added */
			.person-enter.person-enter-active{
				opacity: 1;
			}


			/* This is the class that will be animated *FROM* when a person is removed */
			.person-leave{
				-webkit-transition: 1s linear all;
				-moz-transition: 1s linear all;
				-ms-transition: 1s linear all;
				-o-transition: 1s linear all;
				transition: 1s linear all;
				opacity: 1;
			}

			/* This is the class that will be animated *TO* when a person is removed */
			.person-leave.person-leave-active{
				opacity: 0;
			}


		
	
	
		
Add
{{person.name}}
//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js //Initialisation stuff, note that you don't need any of this for animations, just using it so there's something to see function PeopleController($scope){ $scope.name = ""; $scope.people = [ { name: "Santa Clause"}, { name: "Easter Bunny"}, { name: "Tooth Fairy"}, { name: "Chris Owens"}, { name: "Phillip Farnsworth"}, { name: "Clark Kent"}, { name: "Lana Lang"} ]; $scope.removePerson = function(row){ $scope.people.splice(row, 1); } $scope.addPerson = function(){ $scope.people.push({name: $scope.name}); $scope.name = ""; } }

Problems
If you’re having issues, one of the first things to check is that you’re on the right version of angular. There have been a lot of changes and many of the styles used in one this version don’t seem to work in the older ones. If there’s anything else that’s not working let me know!

Where to From Here?
There’s heaps more that nganimate can do, make sure you checkout http://www.nganimate.org/.

Cannot set property ‘show’ of undefined at new DeathrayMenuController – AngularJS

Hey everyone,

I’ve just started working my way through AngularJS by Brad Green & Shyam Seshadri. Unfortunately I ran into a bit of an issue on page 23 (line 19):

TypeError: Cannot set property 'show' of undefined
    at new DeathrayMenuController (http://127.0.0.1/:18:27)
    at d (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:28:174)
    at Object.instantiate (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:28:304)
    at $get (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:52:239)
    at $get.g (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:43:348)
    at m (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:6:494)
    at i (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:43:213)
    at e (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:39:307)
    at e (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:39:324)
    at e (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js:39:324) 

The solution to this problem turned out to be pretty straight forward, just set the menu state in a similar fashion to that used in the previous exercises:


	
		Your Shopping Cart
	
	
		
		
Toggle Menu
  • Stun
  • Disintergrate
  • Erase
//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js function DeathrayMenuController($scope){ /*$scope.menuState.show = false; //Switch this line with the one below $scope.menuState = {show: false}; $scope.toggleMenu = function(){ $scope.menuState.show = !$scope.menuState.show; } $scope.erase = function(){ window.alert('erased'); } $scope.disintergrate = function(){ window.alert('Disintergrated'); } $scope.stun = function(){ window.alert('Stunned'); } } <!--http://controllers.js-->