I have been following a tutorial on the Ionic Framework, which utilizes Angular JS to develop a basic Todo application. The app adds a new task by utilizing the .push()
method to append a new task object to an array of task objects.
An issue arises when attempting to add more than one task. I encounter the following error:
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: task in tasks, Duplicate key: object:00C
http://errors.angularjs.org/1.2.4/ngRepeat/dupes?p0=task%20in%20tasks&p1=object%3A00C
I have tried implementing the solution provided in this answer and this blog post, which suggests using track by $index
. However, it does not work as expected for me.
Although it eliminates the error, adding a new task updates all objects in the array with that same task. In the list of tasks within the ng-repeat
block, each task appears to be identical to the newly added task.
I am unsure of what mistake I am making here. Could it be related to the manner in which I push objects onto the array? As a novice in Angular.js, I may be overlooking something essential.
The HTML code is as follows:
<body ng-app="todo" ng-controller="TodoCtrl">
<side-menus>
<!-- Central content -->
<pane side-menu-content>
<header class="bar bar-header bar-dark">
<h1 class="title">Todo</h1>
<!-- New Task button-->
<button class="button button-icon" ng-click="editTasks()">
<i class="icon ion-edit"></i>
</button>
<button class="button button-icon" ng-click="newTask()">
<i class="icon ion-compose"></i>
</button>
</header>
<content has-header="true">
<!-- List and list items -->
<list>
<item ng-repeat="task in tasks track by $index">
{{task.title}}
</item>
</list>
</content>
</pane>
<!-- Left menu -->
<side-menu side="left">
<header class="bar bar-header bar-dark">
<h1 class="title">Projects</h1>
</header>
</side-menu>
<!-- Add a new task -->
<script id="new-task.html" type="text/ng-template">
<div class="modal">
<!-- Modal header bar -->
<header class="bar bar-header bar-secondary">
<h1 class="title">New Task</h1>
<button class="button button-clear button-positive" ng-click="closeNewTask()">Cancel</button>
</header>
<!-- Modal content area -->
<content has-header="true">
<form ng-submit="createTask(task)">
<div class="list">
<label class="item item-input">
<input type="text" placeholder="What do you need to do?" ng-model="task.title">
</label>
</div>
<div class="padding">
<button type="submit" class="button button-block button-positive">Create Task</button>
</div>
</form>
</content>
</div>
</script>
</side-menus>
</body>
This is my JavaScript code:
angular.module('todo', ['ionic'])
.controller('TodoCtrl', function($scope, Modal) {
// No longer need testing data
$scope.tasks = [];
// Create and load the Modal
Modal.fromTemplateUrl('new-task.html', function(modal) {
$scope.taskModal = modal;
}, {
scope: $scope,
animation: 'slide-in-up'
});
// Called upon form submission
$scope.createTask = function(task) {
console.log('task', task);
$scope.tasks.push(task);
console.log('$scope.tasks', $scope.tasks);
$scope.taskModal.hide();
};
// Open the new task modal
$scope.newTask = function() {
$scope.taskModal.show();
};
// Close the new task modal
$scope.closeNewTask = function() {
$scope.taskModal.hide();
};
});