1

I am on day 2 of Angular and am trying to create a directive. The idea is that I have several images of quilts to display and I don't want to repeat the same HTML. Here's an index.html snippet showing a use of the new directive and two 'arguments' I'll need in the partial:

<ng-samplequilt imgPath="img/t_3x3_no_sashing/jpg"
                text="This is a 3x3 quilt without sashing.">
</ng-samplequilt>

Here's the partial:

<div>
    <img src="{{imgPath}}"/>
    <div>
        {{text}}
    </div>
</div>

Finally, there's the Directive (which may or may not work):

  .directive('SampleQuilt', ['imgPath','text',function(imgPath, text) {
        return {
            restrict: 'E',
            templateUrl: 'partials/sample_quilt.html'
            };
  }])

So I'm clearly a little over my head. I've read a good deal of the docs and some examples, but none seem to be quite what I'm doing. Or perhaps I have not internalized enough for it to stick.

I'm not looking for a full solution here; I don't mind working through it. But I am stuck - I don't know how to get imgPath and text to make their way to the partial where they can be used.

Also, Directives have embedded controllers. How does the partial know to refer to this controller? Why does it even have access to it, given it's buried in the Directive?

Thanks for a boot in the right direction.

EDIT -

Thanks to @Dalorzo I seem to have a solution.

First, his idea about defining the scope in the Directive worked.

Second, I named the directive "SampleQuilt". This did not work - the directive did nothing/could not be found. When I renamed it to sampleQuilt, however, the internal name translation worked. For similar reasons, the HTML had to refer to img-path, not imgPath.

Here are the three files now.

The index.html snippet:

<sample-quilt img-path="img/t_3x3_no_sashing.jpg"
              text="This is a 3x3 quilt without sashing.">
</sample-quilt>

The partial:

<div>
    <img src="{{img-path}}"/>
    <div>
        {{text}}
    </div>
</div>

The directive:

  .directive('sampleQuilt', function() {
        return {
            restrict: 'E',
            scope:{ imgPath: "@", text: "@"  },
            templateUrl: 'partials/sample_quilt.html'
            };
  })
  ;

EDIT 2 -

The above doesn't work - I was getting burned by browser caching.

It seems as if this snippet in index.html is curious...

<sample-quilt img-path="img/t_3x3_no_sashing.jpg"
              text="This is a 3x3 quilt without sashing.">
</sample-quilt>

The img-path attribute can apparently be spelled three different ways: img-path, 'imgPath', and img_path. All are converted to imgPath internally. When displaying the value in the partial, imgPath is correct.

Here's the corrected partial:

<div>
<img src="{{imgPath}}"/>
<div>
{{text}}
</div>
</div>
Tony Ennis
  • 12,000
  • 7
  • 52
  • 73

1 Answers1

1

Based on your example above I think this should be what you intent:

var app = angular.module('demo',[]);

app.directive('SampleQuilt', function() {
        return {
            restrict: 'E',
            scope:{ imgPath: "@", text: "@"  },
            templateUrl: 'partials/sample_quilt.html'
            };
  });

By adding scope to the directive we create an "isolated scope". With this approach scope can capture attributes in 3 ways:

  1. @ Captures the attribute value from the DOM as string value.
  2. = Evaluates the attribute as property of the parent scope.
  3. & Evaluates the attribute as method of the parent scope.

You can read more about it here:

http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/

Regarding your html:

  • Remove ng and don't use it as part of your directives they are reserved by the angular team and it is good to avoid them to avoid conflicts. You can read more about Angular Naming Conventions here
  • Cases (camel case or pascal case) means dash in angular directives so SampleQuilt needs to be used as sample-quilt in the html.

Sample:

<sample-quilt imgPath="img/t_3x3_no_sashing/jpg"
                text="This is a 3x3 quilt without sashing.">
</sample-quilt>

Regarding your last question about the controller on directives. Directives returned object has a controller property that you can use like:

 app.directive('SampleQuilt', function() {
        return {
            restrict: 'E',
            controller: 'myDirController', /* <--- Controller Declaration */
            scope:{ imgPath: "@", text: "@"  },
            templateUrl: 'partials/sample_quilt.html'
            };
  });



app.controller('myDirController', ['$scope', function ($scope) {
    // My Directive Controller implementation      
}]);
Community
  • 1
  • 1
Dalorzo
  • 19,834
  • 7
  • 55
  • 102