Search code examples
javascriptangularjstastypierestangular

Using ng-model with ng-options and Restangular with AngularJS


I'm having issues with getting items in my select element's option list to be set as selected. My server backend is Django 1.5 with TastyPie as the API.

The Template (simplified)

<select
    ng-model='dataService.major_minor.department'
    ng-options='d.name for d in dataService.departments'
    name='department'
    class='select2'
    required>
</select>

The Data Service

majorMinor.factory('dataService', function($rootScope, Restangular) {
    var self = {};

    self.degrees = [];
    self.departments = [];
    self.major_minor = false;
    self.majors_and_minors = [];

    self.fetch_degrees = function() {
        Restangular.all('degree').getList().then(function(results) {
            self.degrees = results;
        });
    };

    self.fetch_departments = function() {
        Restangular.all('department').getList().then(function(results) {
            self.departments = results;
        });
    };

    self.fetch_major_minor = function(majorMinorID) {
        Restangular.one('major-minor', majorMinorID).get().then(function(result) {
            self.major_minor = result;
        });
    };

    self.fetch_major_minor_list = function() {
        Restangular.all('major-minor').getList().then(function(results) {
            self.majors_and_minors = results;
        });
    };

    self.fetch_degrees();
    self.fetch_departments();
    self.fetch_major_minor_list();

    return self;
});

The Controller

majorMinor.controller('EditCtrl',
    function($scope, $routeParams, dataService) {

        $scope.dataService = dataService;
        $scope.dataService.major_minor = false;
        $scope.dataService.fetch_major_minor($routeParams.majorMinorID);
    }
);

The issue I'm grappling with is that major_minor.department is a foreign key. TastyPie is returning a full object, so it's not just the department URI. The dataService.departments array is an array of all the departments available to this user. If you were to compare the major_minor.department to dataService.departments[indexOfDepartment], they would be equal.

Any thoughts why ng-model is not correctly selecting an ng-option? It's possible there is a gap in my understanding of Angular/Restangular as this is only my 2nd project using both.


Solution

  • Jack, I ran into a similar problem and was able to solve it by tweaking the ng-options

    <select
        ng-model='dataService.major_minor.department.id'
        ng-options='d.id as d.name for d in dataService.departments'
        name='department'
        class='select2'
        required>
    </select>
    

    I then changed my angular service to change the dataservice.major_minor.department from an object to the ID before I POSTed to my express ReSTful service. That should give you the foreign key coming across the wire in the payload, rather than the denormalized object. It's a coffeescript service, so a little different than the factory approach you're taking.

       save: (major_minor) ->
          major_minor.department = major_minor.department?._id
          @$http.post("/api/major_minor/", major_minor)
    

    The angularjs docs talk about this in the ng-options section here: https://docs.angularjs.org/api/ng/directive/select

    Hope that helps, especially future searchers that are running into this issue.