简体   繁体   中英

AngularJS weird error when creating simple directive

I'm trying to create simple directive in angularJs and don't understand why the code below gives me following error:

Error: [$compile:tplrt] http://errors.angularjs.org/undefined/$compile/tplrt?p0=taWithMessage&p1=customButton.html

the code is:

<!doctype html>
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>

    <script>

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

    app.directive("taWithMessage",function() {
        return {
            templateUrl: "customButton.html",
            replace: true
            };
        }

    );    

    </script>

  </head>
  <body>

    <div ng-app="aaa">

    <script type="text/ng-template" id="customButton.html">

        <p>blah <em>blah<em>blah</em></em> blahHello, 
        <h2>kkk</h2>
        <input type="text" placeholder="Enter a name here" ng-keypress="valid=true"/></p>

    </script> 

        <form>

        <div ta-with-message></div>

            <input type="submit">

        </form>
    </div>
  </body>
</html>

What I don't understand is that it works when I replace h2 with say span eg:

<p>blah <em>blah<em>blah</em></em> blahHello, 
<span>kkk</span>
<input type="text" placeholder="Enter a name here" ng-keypress="valid=true"/></p>

Does it have something to do with display of the element? Why would that be happening and how would I fix it?

This page of AngularJS error reference should help you:

Further explanation

Auto-closing <p> tag

First (non-working) example in question contains a slight HTML markup error.

Why? Because <p> only allows phrasing content inside it. Heading tags are not phrasing content. When browser sees a non-phrasing-content (for example, heading) tag inside <p> , it implicitly adds </p> .

Not putting </p> before <h2> is not an error, it's allowed by HTML specs:

The end tag may be omitted if the <p> element is immediately followed by an <address> , <article> , … <h1> , <h2> , <h3> , … or another <p> element, or if there is no more content in the parent element and the parent element is not an <a> element.

But in the end the first example in question is interpreted by browser like this:

    <p>blah <em>blah<em>blah</em></em> blahHello,</p> 
    <h2>kkk</h2>
    <input type="text" placeholder="Enter a name here" ng-keypress="valid=true"/>

Note how </p> changed its position from after <input> to before <h2> .

Incompatible directive template

This makes such directive template incompatible, because it then has more than one root element . By AngularJS docs linked above, your directive template must have all its content inside a single top-level tag. However, your first example after browser interpretation turns out to have three top-level tags.

When you change <h2> to <span> your example is OK, since <p> doesn't auto-close anymore ( <span> is phrasing content).

What you can do

Wrap your template in a <div> . Unlike <p> , it can contain any type of content. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM