Mangular.js

I recently started having a look at AngularJS to replace HTML + jQuery spaghetti code, and it is pretty neat. I looked at the todo example on the main website and as simple as it may be, I do think Mangler.js can simplify it a bit more, and I’m tempted to coin the term “Mangular.js”.;) Here’s how.

The original Angular.js todo app

This code comes straight from the AngularJS website’s main page, look over there if you need explanation.

<!DOCTYPE html>
<html ng-app="todoApp">
<head>
	<title>AngularJS ToDo</title>
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
	<script>
	
angular.module('todoApp', [])
	.controller('TodoController', ['$scope', function($scope) {
		$scope.todos = [
			{ text: 'learn angular', done: true },
			{ text: 'build an angular app', done: false }
		];

		$scope.addTodo = function() {
			$scope.todos.push({ text: $scope.todoText, done: false });
			$scope.todoText = '';
		};

		$scope.remaining = function() {
			var count = 0;
			angular.forEach($scope.todos, function(todo) {
				count += todo.done ? 0 : 1;
			});
			return count;
		};

		$scope.archive = function() {
			var oldTodos = $scope.todos;
			$scope.todos = [];
			angular.forEach(oldTodos, function(todo) {
				if (!todo.done) $scope.todos.push(todo);
			});
		};
	}]);

	</script>
	
	<style>
		.done-true {
			text-decoration: line-through;
			color: grey;
		}
	</style>
</head>
<body>
	<h2>Todo</h2>
	<div ng-controller="TodoController">
		<span>{{remaining()}} of {{todos.length}} remaining</span>
		[ <a href="" ng-click="archive()">archive</a> ]
		<ul class="unstyled">
			<li ng-repeat="todo in todos">
				<input type="checkbox" ng-model="todo.done">
				<span class="done-{{todo.done}}">{{todo.text}}</span>
			</li>
		</ul>
		<form ng-submit="addTodo()">
			<input type="text" ng-model="todoText" size="30" placeholder="add new todo here">
			<input class="btn-primary" type="submit" value="add">
		</form>
	</div>
</body>
</html>

Simplification using Mangler.js

.todo

Instead of having a simple array to store the todo items, wrap it in a managed Mangler object:

$scope.todos = Mangler([
	{ text: 'learn mangular', done: true },
	{ text: 'build a mangular app', done: false }
]);

HTML and Angular templates

In line with the above changes, you have to change all references to the todo array to todo.items. This affects the {{todos.length}} template tag and the ng-repeat="todo in todos" directive.

.addTodo()

Nothing has to change here, as the todo Mangler object supports the .push() method, just like an array.

.remaining()

Instead of a manual loop, simply use the .find() method to return a sub-set of your items:

$scope.remaining = function() {
	return $scope.todos.find({ done: false }).length;
};

The .find() method returns an array of all items matching the filter, returning the .length property simply counts them in a single line.

.archive()

Using the same condition as above, the Mangler object’s .filter() method removes non-matching items from the .items array:

$scope.archive = function() {
	$scope.todos.filter({ done: false });
};

The shorter Mangular.js todo app

Mangler.js can greatly simplify working with JavaScript objects and arrays, you no longer have to write multiple lines of code for simple operations. Here’s the shortened code:

<!DOCTYPE html>
<html ng-app="todoApp">
<head>
	<title>Mangular.js ToDo</title>
	<script src="mangler.js"></script>
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
	<script>
	
angular.module('todoApp', [])
	.controller('TodoController', ['$scope', function($scope) {
		$scope.todos = Mangler([
			{ text: 'learn mangular', done: true },
			{ text: 'build a mangular app', done: false }
		]);

		$scope.addTodo = function() {
			$scope.todos.push({ text: $scope.todoText, done: false });
			$scope.todoText = '';
		};

		$scope.remaining = function() {
			return $scope.todos.find({ done: false }).length;
		};

		$scope.archive = function() {
			$scope.todos.filter({ done: false });
		};
	}]);

	</script>
	
	<style>
		.done-true {
			text-decoration: line-through;
			color: grey;
		}
	</style>
</head>
<body>
	<h2>Todo</h2>
	<div ng-controller="TodoController">
		<span>{{remaining()}} of {{todos.items.length}} remaining</span>
		[ <a href="" ng-click="archive()">archive</a> ]
		<ul class="unstyled">
			<li ng-repeat="todo in todos.items">
				<input type="checkbox" ng-model="todo.done">
				<span class="done-{{todo.done}}">{{todo.text}}</span>
			</li>
		</ul>
		<form ng-submit="addTodo()">
			<input type="text" ng-model="todoText" size="30" placeholder="add new todo here">
			<input class="btn-primary" type="submit" value="add">
		</form>
	</div>
</body>
</html>
Share Button
Tagged with: , ,

Leave a Reply