Error in Tutorial Chapter 5 - [ngRepeat:dupes] Duplicates in a repeater are not allowed


#1

Hi there!

I’m following the tutorial on chapter 5, and I’ve just added the modal to create a new task and the JS to control it.

When I add a new task at first it seems to update fine, but then when I try to add another task it fails and gives me the following error in the console:

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:00S

And instead of seeing my new task underneath my first task in the list, I just see this new task as the only one in the list.

My HTML:

<body ng-app="todo" ng-controller="TodoCtrl">
  <side-menus>

    <!-- Center 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">
		    <!-- our list and list items -->
		    <list>
		      <item ng-repeat="task in tasks">
		        {{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>	
  </side-menus>
  
  <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>		
</body>

Javascript:

angular.module('todo', ['ionic'])

.controller('TodoCtrl', function($scope, Modal) {
  // No need for testing data anymore
  $scope.tasks = [];

  // Create and load the Modal
  Modal.fromTemplateUrl('new-task.html', function(modal) {
    $scope.taskModal = modal;
    console.log($scope);
  }, {
    scope: $scope,
    animation: 'slide-in-up'
  });

  // Called when the form is submitted
  $scope.createTask = function(task) {
    $scope.tasks.push(task);
    console.log(JSON.stringify($scope.this.tasks));
    $scope.taskModal.hide();
  };

  // Open our new task modal
  $scope.newTask = function() {
    $scope.taskModal.show();
  };

  // Close the new task modal
  $scope.closeNewTask = function() {
    $scope.taskModal.hide();
  };
});

#2

I posted this issue as a question on Stack Overflow, and here’s the solution that came back and it fixed the problem for me:

The problem looks like you are not creating independent task instances. It appears that your modal is binding to a single task instance and attempting to add the same exact reference each time. Try something like the following:

JS

// Open our new task modal
$scope.newTask = function() {
   $scope.editTask = {};
   $scope.taskModal.show();
};

HTML

<form ng-submit="createTask(editTask)">
      <div class="list">
         <label class="item item-input">
            <input type="text" placeholder="What do you need to do?" ng-model="editTask.title">
         </label>
      </div>
      <div class="padding">
         <button type="submit" class="button button-block button-positive">Create Task</button>
      </div>
   </form>