1

I'm playing around with basic Angular JS stuff. I thought I knew custom directives pretty well but I'm only able to get them to show up in the template if I use them as element attributes. And I'm not wanting to use comments or class names as those are not best practices. Based on documentation and other sources these directives SHOULD work as an element AND an element attribute.

In my index you'll see that I'm declaring my directives twice -- in the top block as attributes (which work) and the bottom block as elements (which don't work). I'm hours deep into this problem. Any insight is tremendously appreciated.

Index.html

<head>
  <title>Test App</title>

  <meta name="viewport" content="width=device-width, initial-scale=1">

  <link href='styles/css/style.css' rel='stylesheet' type="text/css">

  <script src="vendor/angular_1.2.13/angular.min.js"></script>

</head>

<body ng-app="testApp" class="app__body">
    <div class="body__inner">
        <header>
          <h1>My New Test App</h1>
        </header>

        <div first-directive></div>
        <div second-directive></div>

        <first-directive></first-directive>
        <second-directive></second-directive>

    </div>
    <script src="scripts/all-in-one.js" type="text/javascript"></script>
</body>

all-in-one.js

'use strict';

angular.module('testApp', [])

.directive('firstDirective', function() {
    return {
        template: 'Hello World'
    }
})

.directive('secondDirective', function() {
    return {
        templateUrl: '/scripts/directives/secondDirective.js'
    }
})

.controller('firstCtrl', function($scope) {
    $scope.message = "Hola Amigos!"
})

secondDirective.js

<div>
    <h2>Esta Aqui!</h2>
</div>
Tomas Ramirez Sarduy
  • 17,294
  • 8
  • 69
  • 85
Jef
  • 320
  • 5
  • 14
  • Are you having a cross origin error in your console?....if you are, you need to serve the html templates using something like Mamp – Pato Salazar Apr 02 '17 at 03:20
  • @PatoSalazar, what does it has to do cross origin with this question? – Tomas Ramirez Sarduy Apr 02 '17 at 03:23
  • I tried to load his code, in Chrome, and I got that error. If I load the site using Mamp then the code works – Pato Salazar Apr 02 '17 at 03:24
  • this to be exact `XMLHttpRequest cannot load file:///Applications/MAMP/htdocs/personal%20project/stackoverflow/secondDirective.js. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.` – Pato Salazar Apr 02 '17 at 03:25
  • @PatoSalazar, of course, you get that error because you are trying to load `/scripts/directives/secondDirective.j` which doesn't exist. – Tomas Ramirez Sarduy Apr 02 '17 at 03:32
  • well i put secondDirective.js as a root file, and call it with the correct path using Mamp and it loads for me. – Pato Salazar Apr 02 '17 at 03:34

2 Answers2

6

In angular 1.2x you have to set the restrict value to include 'E' as its not included by default.

.directive('secondDirective', function() {
    return {
        restrict: 'EA',
        template: '<div><h2>Esta Aqui!</h2></div>'
    }
})

Upgrading to a newer angular version, 'EA' is set as a default value.

Ace
  • 969
  • 4
  • 10
  • I think by default the value is EA, meaning that both element tags and attribute names can invoke the directive. – Tomas Ramirez Sarduy Apr 02 '17 at 03:21
  • @TomSarduy It is in versions greater then 1.2x – Ace Apr 02 '17 at 03:44
  • look copy his code... make sure the path to the files are ok, and open them using mamp... the code of the question works... it is a cross origin issue – Pato Salazar Apr 02 '17 at 03:46
  • @Ace you are right... I ran 1.2.13 version and need to have `restrict: 'EA`. But I still get a cross origin error if I don't use Mamp... – Pato Salazar Apr 02 '17 at 03:47
  • @PatoSalazar, the issue it's not related with CORS, since the directives are rendered using the attributes. Ace, good catch! +1 – Tomas Ramirez Sarduy Apr 02 '17 at 03:51
  • @TomSarduy his question says that the directives he declares as html elements are the ones that are failing... the attribute ones are working `in the top block as attributes (which work) and the bottom block as elements (which don't work)` – Pato Salazar Apr 02 '17 at 03:54
  • So yeah... so probably @Ace is right... but if he is trying to load the templates from the browser he will get a CORS error independently if he use using or not `restrict: 'EA'` – Pato Salazar Apr 02 '17 at 03:56
  • @PatoSalazar: Yes, so they are rendered via *ATTRIBUTES*, so the templates are founded and rendered. There is a difference between rendering them as *ELEMENTS* and as *ATTRIBUTES* – Tomas Ramirez Sarduy Apr 02 '17 at 03:56
  • Dude in his question he is asking why when he uses `templateUrl ` in the second directive is not working. I know there is a difference between elements and attributes. But again he says my first declaration works (firstDirective which is using `template`) and my second does not work (which uses `templateUrl`).... using templateUrl will give you the CORS error if you are accessing the templateUrl from the browser that is why I am pointing that out – Pato Salazar Apr 02 '17 at 04:11
  • @Ace answer even changes `templateUrl` to `template` to make it work in the second directive. Now he is right when saying that 1.2.13 requires explicit `restrict: 'EA'`...this will make `template` and `templateUrl` work – Pato Salazar Apr 02 '17 at 04:13
-1

[Update] A user @Ace points out, you might be using and old version of Angular. You need to declare restrict: 'EA' when you return to make it work.

Also, and just in case, if you ran your code and get a cross origin error in the console. Here AngularJS Error: Cross origin requests are only supported for protocol schemes: http, data, chrome-extension, https says it is because you are trying to load an html template from the browser. You need to use something like MAMP.

Community
  • 1
  • 1
Pato Salazar
  • 1,447
  • 12
  • 21