2

I have an AngularJS frontend and REST (Jersey) backend that reads a list of book titles a teacher has assigned to a Student. There are two views/pages - list and edit. A list page is a table that shows Student Name and Currently Assigned Book Title.

A teacher can select to edit the book assigned to a student. On selecting "Edit", teacher is taken to the Edit view/page that has a dropdown containing list of available book titles to read in the library and is populated by calling REST service Books.getUnassigned(). When a book is assigned to any student the backend will remove the book title from the unassigned list and add it to assigned list (Books.getAssigned()). So on the edit page I need to call the service, push the current assigned book title to that array and also set the default to the current book title.

  <select ng-model="bookToAssign">
                <option ng-repeat="book in available_books" value="{{book}}">{{book}}</option>
  </select>

Below is my service call. When the edit page is loaded $rootScope.args.arg contains a json object with all the data that needs to be passed from the previous page to the edit page - verified that the object is correct.

 $scope.available_books= NaiSvc.getUnassignedBooks.query(
        function(data){
            alert('success, got data: ', data);
            if($rootScope.args.arg !=null){
               data.push($rootScope.args.arg);  //verified this gets the right object
                $scope.bookToAssign.setDefault = data[data.length-1];
            }
        }, function(err){
            alert('request failed');
        }
    );

In function success callback when I try to do bookToAssign.setDefault, I get the error: TypeError: Cannot read property 'setDefault' of undefined. Can someone please guide me whats going on here? Appreciate the help

8
  • bookToAssign appears to be a javascript global....where is it defined? Also seems strange that ng-model of select tag has same variable name. My guuess is if you use $scope.bookToAssign.setdefault will also run into conflict with ng-model. Provide a demo Commented Oct 27, 2013 at 18:57
  • I think you meant to write $scope.bookToAssign. That should fix your problem. Commented Oct 27, 2013 at 18:58
  • @charlietfl the way angularJS works by declaring ng-model="xyz" in html, the object xyz gets created - very cool feature I think Commented Oct 27, 2013 at 19:17
  • @mortalapeman I forgot to add $scope. infront of bookToAssign. Good Catch. I updated the question. The error remains.. Commented Oct 27, 2013 at 19:18
  • yes error will remain because you now have a conflict with ng-model and also likely you never declared $scope.bookAssign as an object in order for it to have any properties like bookAssign Commented Oct 27, 2013 at 19:21

1 Answer 1

3

Base on your question, I've written up a working example that sound like what you want. Take a look at it and let me know if I missed something.

I've set up a landing page that lists some students and their books. I use a routes to pass data between views to setup the edit page. I used the ng-options directive to list the books and bind them accordingly.

Demo plunker

Javascript:

angular.module('plunker', [])

.config(function($routeProvider) {
  $routeProvider.when('/list', {
    templateUrl: 'list.html',
    controller: 'ListCtrl'
  })
    .when('/edit/:book', {
      templateUrl: 'edit.html',
      controller: 'EditCtrl'
    })
    .otherwise({
      redirectTo: '/list'
    });
})


.service('BookService', function($q, $timeout) {
  var unassigned = ['English', 'History'];

  this.getUnassigned = function() {
    var deferred = $q.defer();

    // Simulate async call to server.
    $timeout(function() {
      deferred.resolve(unassigned);
    });

    return deferred.promise;
  };

})

.controller('EditCtrl', function($scope, $routeParams, BookService) {
  // student.book needs to be set to avoid null select option
  $scope.student = {book: $routeParams.book, name: $routeParams.name };
  $scope.unassigned = BookService.getUnassigned().then(function(data) {
    return [$routeParams.book].concat(data);
  });
})

.controller('ListCtrl', function($scope) {
  $scope.students = [{
    name: 'Billy',
    book: 'Math'
  }, {
    name: 'Joe',
    book: 'Science'
  }];
});

HTML:

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js" data-semver="1.1.5"></script>
    <script src="app.js"></script>
    <script type="text/ng-template" id="list.html">
      <table>
        <theader>
          <tr><td>Name</td><td>Book</td><td></td></tr>
        </theader>
        <tbody>
          <tr ng-repeat="student in students">
            <td>{{ student.name }}</td><td>{{ student.book }}</td><td><a ng-href="#/edit/{{ student.book }}?name={{student.name}}">Edit</a></td>
          </tr>
        </tbody>
      </table>
    </script>
    <script type="text/ng-template" id="edit.html">
      <div>
        <p>Current Student: {{ student.name }}</p>
        <label>Select A Book: </label>
        <select ng-model="student.book" ng-options="book for book in unassigned">
        </select>
        <p> You have selected: {{student.book}}</p>
    </script>
  </head>

  <body>
    <div ng-view></div>
  </body>
</html>
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the plunkr. It did exactly what I needed to! I had to change from doing <options> in <select> to ng-options instead. Not quite sure why that makes a difference but that solved the issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.