Adding methods and forms

Next, let's make it possible to add new students dynamically so that we don't have to rely on sample data. We'll switch the order up and start with our HTML and directives this time, so that we have an idea of how we want the page to look:

student-roster/index.html

<!doctype html>
<html ng-app="studentRoster">
<head>
  <title>Student App</title>
  <script src="lib/angular.js"></script>
  <script src="app.js"></script>
  <script src="js/StudentsController.js"></script>
  <link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
  <div class="container" ng-controller="StudentsCtrl">
    <div class="row">
      <div class="col-md-12">
        <h2>Student List</h2>
        <ul>
          <li ng-repeat="item in students">
            {{item.name}}
          </li>
        </ul>
      </div>
      <div class="col-md-4">
        <h2>New Student</h2>
        <form ng-submit="addStudent()" class="form-inline" role="form">
          <div class="form-group">
            <input type="text" ng-model="studentName" class="form-control" placeholder="Enter name">
          </div>
          <button type="submit" class="btn btn-default">Submit</button>
        </form>
      </div>
    </div>
  </div>
</body>
</html>

We've added a new column below where we are listing out the students. It contains a form to add a new student. The ng-submit directive will trigger the addStudent method when that form is submitted. The directive ng-model creates a new property on $scope in our StudentsCtrl controller called studentName and sets it to the value of the input. Here, studentName is the model, just like students is the model in the part of the app that lists the students out.

Now, let's create the addStudent method to our StudentsCtrl controller in order to make this form work:

student-roster/js/StudentsController.js

studentRoster.controller('StudentsCtrl', function StudentsCtrl($scope) {
  $scope.students = [];
  $scope.addStudent = function() {
    $scope.students.push({ name: $scope.studentName });
    $scope.studentName = null;
  };
});

We've removed the sample data from the $scope.students array because now we will be pushing a new student object into that array when we use the addStudent method. This method will create a new student object based on the user's input and push it into the students array. It then resets the studentName model to null so that the field in the HTML is cleared.

We can now add our own students to the page!

Next, let's add the ability to delete students. Again, we'll start with the HTML and directives. Change the <div> holding the student list so that it includes the following <a> tag:

student-roster/index.html

...
<div class="col-md-12">
  <h2>Student List</h2>
  <ul>
    <li ng-repeat="item in students">
      {{item.name}} <a ng-click="deleteStudent(item)">Delete</a>
    </li>
  </ul>
</div>
...

We have added the line <a ng-click="deleteStudent(item)">Delete</a> inside the ng-repeat directive from the last lesson. ng-click is very similar to ng-submit - except, as you might have guessed, it gets triggered on a click instead of a submit action. This is similar to attaching a click handler to an HTML element in jQuery, except here instead of using a jQuery selector with the dollar sign, we are using a directive on an HTML element. So when the word "Delete" is clicked, the app will run the deleteStudent method. We have passed item into the method so it knows which particular object to delete. Here's the deleteStudent method in our controller. Add this to js/StudentsController.js right after the declaration of the addStudent method, but before the closing brackets of the studentRoster.controller method.

student-roster/js/StudentsController.js

...
$scope.deleteStudent = function(student) {
  var index = $scope.students.indexOf(student);
  $scope.students.splice(index, 1);
};
...

We pass in the student as an argument to the deleteStudent method, use the built-in JavaScript method indexOf to find the index of the student in our $scope.students array, and call the JavaScript splice method on it. The splice method removes elements from an array. Its first argument is an integer, which is the index where it should start removing array elements. The second argument is the number of elements we want to delete. So in this case we are starting our removal at the index of the student and only deleting that one element.

Summary

An Angular form:

<form ng-submit="addStudent()" class="form-inline" role="form">
  <div class="form-group">
    <input type="text" ng-model="studentName" class="form-control" placeholder="Enter name">
  </div>
  <button type="submit" class="btn btn-default">Submit</button>
</form>
  • Add the ng-submit directive to run a particular function when the form is submitted.
  • Use ng-model to create a new property on the $scope of that particular controller and set it equal to the name passed into that directive.

The directive ng-click can be used to call a method or set a property when not using a form.