angularjs directives passing in ng-model

David Jones
@david3jones
avatar-davidejones

I’m pretty new to angularjs and I’ve been working through what I can learning a lot from egghead.io videos, stackoverflow and just plain old trial and error. So I’m actually writing a new checkout at the moment and in doing so I’ve written a series of directives to do some pretty basic things just a year dropdown and a month dropdown and day dropdown making use of a html select and the ng-options directive. The main reason is just to prepopulate the data in the directive and use a series of options to control the range or order of the data, pretty simple stuff. Anyway over time I’ve been building into this trying to make it a more reusable being able to pass in different attributes so that it is more flexible until i hit a roadblock. The roadblock was i kept getting the error “Error: Multiple directives [ngModel, ngModel] asking for ’ngModel’ controller on:” and this was giving me the hardest time. All i was trying to do was pass in ng-model to my directive. Here is a rough example of the kind of code i was using

<selectnames ng-model="firstname"></selectnames>
app.directive("selectnames", function() {
        return {
            restrict: 'E',
            scope: {
                ngModel: '='
            },
            controller: function($scope, $element) {
                $scope.names = ['David', 'Adam', 'Michael', 'Alison', 'Valdimar', 'Jenni'];
            },
            link: function(scope, element, attrs, ctrls) {
            },
            template:'<select ng-options="name for name in names" ng-model="ngModel"></select>',
            replace:true
        }
});

At the time being new to angular and googling around i came to the conclusion that for whatever reason it wasn’t possible. Maybe the fact i was using ng-options and that did some code with ng-model on its own? I came across a stackoverflow post and started using a different variable to pass the model around and that seemed to be working fine. This is what i ended up using as a work around

<selectnames ngmodelvar="firstname"></selectnames>
app.directive("selectnames", function() {
        return {
            restrict: 'E',
            scope: {
                ngmodelvar: '='
            },
            controller: function($scope, $element) {
                $scope.names = ['David', 'Adam', 'Michael', 'Alison', 'Valdimar', 'Jenni'];
            },
            link: function(scope, element, attrs, ctrls) {
            },
            template:'<select ng-options="name for name in names" ng-model="ngmodelvar"></select>',
            replace:true
        }
});

While this worked great it was really starting to bug me the fact that a core part of angularjs just wasn’t working for me. That I’d now have to use another variable to pass it in and another developer would have to understand that it was a different way of binding. As I did further development on my checkout I could see when i had a directive with an input i didn’t have these issues i could just bind to ngModel and pass it through so what the hell?! Finally after doing a series of basic tests I came across the error “Error: Template must have exactly one root element. was:”, which then lead me to wrap my select directive in a div and that seemed to solve all my ng-model binding issues.

Comments

  • avatar-james
    # James
    Since making this post, have you found a better way to pass in variables to a template?
    • avatar-davidejones
      # davidejones
      I’ve done a couple of different ways of accessing the variables or attributes on the directive. I don’t have them handy but i’ll do some more posts on angularjs soon.
  • avatar-patrick-greene
    # Patrick Greene
    Thank you! Wrapping my template in a solved my own issue!

Comments are currently closed