1

I have a directive and I'm trying to get the Attrs and pass them to the $scope, but I'm not quite sure how to do that. More specifically I'm trying to set attributes in my template equal to what the name is set in my date-picker tag. I tried setting them as a variable, but obviously that didn't work. Help and further clarification is greatly appreciated. Thanks!

HTML

<date-picker id="dateendPicker" name="date_end"></date-picker>

JS

App.directive('datePicker', function(){
  return {
  scope: {
          name : '@'
         },
  restrict: 'AE',
  replace: 'true',
  template: '<div class="date"><div class="input-group"><input type="text" class="form-control" id="{{this_name}}" name="{{this_name}}" ng-model="event.{{this_name}}" required/><span class="input-group-addon"><i class="fa fa-calendar"></i></span></div></div>',
  controller: ['$scope', function($scope){
        $scope.this_name = this_name;
  }],
  link: function(scope, element, attrs){
    var this_name = attrs.name;
  }
  }
});
jaruesink
  • 1,205
  • 2
  • 14
  • 24

3 Answers3

2

Because of how you've defined your directive scope:

  scope: {
      name : '@'
  }

name is already a variable on your scope. If you're not doing anything special with it on your controller\link functions, you can drop them entirely, and in your template reference it with {{name}}. Just note that if you're creating scope bindings with '@', then in your html you should pass your data as an angular expression, meaning:

name="{{date_end}}"
haimlit
  • 2,572
  • 2
  • 22
  • 26
  • More generally, you can also inject $element and $attrs into your controller along with $scope, but you don't need to do that here. – dustyrockpyle Jun 27 '14 at 21:21
  • I guess I didn't specify. I'm hoping to get the name attr to set the value of the attributes="{{this_name}}" in the template. – jaruesink Jun 27 '14 at 21:29
  • Then you can just change it to scope: {this_name : '@name'}, you can even remove the link and controller from your directive. – dustyrockpyle Jun 28 '14 at 06:49
0

As I could see from your snippet, you want to use name attribute as ng-model into directive. I think, you should consider using another type of isolated scope (related SO answer)

Here is my approach (jsFiddle):

app.directive('datePicker', function () {
    return {
        scope: {
            name: '=name'
        },
        restrict: 'AE',
        replace: 'true',
        template: 
            '<div class="date">' +
                '<div class="input-group">' +
                    '<input type="text" ' +
                            'class="form-control" ' +
                            'id="bad-idea-to-make-it-editable-id" ' +
                            'name="{{ name }}" ' +
                            'ng-model="name" ' +
                            'required/>' +
                    '<span class="input-group-addon">' +
                        '<i class="fa fa-calendar"></i>' +
                    '</span>' +
                '</div>' +
            '</div>'
        }
    });

So now you can edit parent scope from directive. But if you dont want this kind of communication between scopes, use @ scope, as @haimlit has mentioned.

Community
  • 1
  • 1
Serhii Holinei
  • 5,758
  • 2
  • 32
  • 46
0

There are some issues with your code snippet: First you do not assign the assign the attrs to the scope but to a local variable, so it won't be available in the controller function.

You could try this:

App.directive('datePicker', function(){
    return {
        scope: {
            name : '@'
        },
        restrict: 'AE',
        replace: 'true',
        template: '<div class="date"><div class="input-group"><input type="text" class="form-control" id="{{this_name}}" name="{{this_name}}" ng-model="event.{{this_name}}" required/><span class="input-group-addon"><i class="fa fa-calendar"></i></span></div></div>',
        controller: ['$scope', function($scope){
            $scope.this_name = this_name;
        }],
        link: function(scope, element, attrs){
            scope.this_name = attrs.name;
        }
    }
});

I do not know if this really works since it is not recommended to use controller and link functions at the same time (taken from the directive guide):

Best Practice: use controller when you want to expose an API to other directives. Otherwise use link.

But according to the docs the attrs are also available as $attrs to the controller function:

App.directive('datePicker', function(){
    return {
        scope: {
            name : '@'
        },
        restrict: 'AE',
        replace: 'true',
        template: '<div class="date"><div class="input-group"><input type="text" class="form-control" id="{{this_name}}" name="{{this_name}}" ng-model="event.{{this_name}}" required/><span class="input-group-addon"><i class="fa fa-calendar"></i></span></div></div>',
        controller: ['$scope', '$attrs', function($scope, $attrs){
            $scope.this_name = $attrs.name;
        }]
    }
});

But you have already defined name in the isolate scope, so it should be availble as scope.name in the conroller or link function:

App.directive('datePicker', function(){
    return {
        scope: {
            name : '@'
        },
        restrict: 'AE',
        replace: 'true',
        template: '<div class="date"><div class="input-group"><input type="text" class="form-control" id="{{this_name}}" name="{{this_name}}" ng-model="event.{{this_name}}" required/><span class="input-group-addon"><i class="fa fa-calendar"></i></span></div></div>',
        link: function(scope, element, attrs){
            console.log(scope.name); // this is your name defined as attribute name="..." on the tag
        }
    }
});
kleinph
  • 151
  • 1
  • 9