Milligran
Milligran

Reputation: 3161

How to add ng-model input values to scope in a angular directive

I am new to angular and trying to create my first directive.

Here is an example:

isrcorderapp.directive "isrcrow", () ->
    restrict:'A'
    controller: 'isrcorders'
    template: '<td><input id="artist" ng-model="{{artist}}"/></td>
                <td><input id="title" ng-model="{{title}}"/></td>
                <td><select id="isrctype" ng-model="{{isrctype}}" ng-options="s.type for s in recordingTypes" class="ng-pristine ng-valid"></select></td>
                <td><input id="duration" ng-model="{{duration}}"/></td>
                <td><input id="year" ng-model={{year}}/></td>
                <td><input type="button" value="Add ISRC" ng-click="AddIsrc()" class="btn btn-small btn-success" />
                    <input type="button" value="Delete" ng-click="RemoveIsrc()" class="btn btn-small btn-danger" />
                </td>'
    replace: false
    scope:
        artist:'@'
        title:'@'
        isrctype:'@'
        duration:'@'
        year:'@'
    link: (scope,element,attr) ->

This directive was working until I added the scope and ng-model in the elements.

Here is a working example before the additions were made:

http://plnkr.co/edit/oxXZlsFIDAbBCYMDOYMH?p=preview

I would like to add the values of the fields(artist.title,isrcType...) to the scope object but I keep getting errors when the web page is loaded:

Error: [$parse:syntax]

How can I fix this? What am I doing wrong here?

Upvotes: 0

Views: 5123

Answers (1)

charlietfl
charlietfl

Reputation: 171679

One rule of thumb with angular is you should always have a dot in ng-model.

Since you are building a collection of rows, data wise think of them first as an array of objects. Then you can use ng-repeat to generate the html from that array....not by using jQUery which doesn't belong in a controller. Adding new rows is done by pushing a new object to array and angular will update DOM accordingly. Similarly, remove from array and angular will remove the html

Here's a working version, including how to remove an object from array to remove a row.

ng-repeat will create a child scope for each row and since we are now using a dot in ng-model the object in child scope will be reference to object in array in the controller parent scope

isrcorderapp.directive("isrcrow", function(){
  return {
    restrict:'A',
    template: '<td><input  ng-model="row.artist"/></td>\
                <td><input ng-model="row.title"/></td>\
                <td><select  ng-model="row.isrctype" ng-change="setState(state)" ng-options="s.type for s in recordingTypes" class="ng-pristine ng-valid"></select></td>\
                <td><input ng-model="row.duration"/></td>\
                <td><input ng-model="row.year"/></td>\
                <td><input type="button" value="Add ISRC" ng-click="AddIsrc()" class="btn btn-small btn-success" />\
                    <input type="button" value="Delete" ng-click="RemoveIsrc(row)" class="btn btn-small btn-danger" />\
                </td>',
    replace: false
  }
});

isrcorderapp.controller("isrcorders", function($scope,$http,$compile) {
    function newItem(){
      return{
        artist:'',
        title:'',
        duration:'',
        year:'',
        isrctype:''
      }
    }
    $scope.recordingTypes = [
        {type:'A'},
        {type:'B'},
        {type:'C'},
        {type:'D'},
        {type:'E'}
        ];
      /* start array with blank object since we don't have ajax source yet*/  
     $scope.items=[newItem()] ;  

    $scope.AddIsrc = function() {
     $scope.items.push(newItem())
    };
    $scope.RemoveIsrc=function(row){
      var index=$scope.items.indexOf(row);
      $scope.items.splice(index,1)
    }    

});

In html I made adjustment of wrapping table within the controller using ng-controller and adding ng-repeat to <tr>

<tr ng-repeat="row in items" isrcrow=""></tr>

DEMO

If you haven't done so already, you should read this highly valuable post "Thinking in AngularJS" if I have a jQuery background?

Upvotes: 4

Related Questions