TL; DR:
在指令的templateUrl方法中使用attr值,在使用子指令时尚未插入attr.最终结果是文字{{attrName}} / something.html.
全文:
我有一个外部指令,其中包含内部指令.诀窍是,这些内部指令也是可以在不知道父母的情况下自己生活的项目.
规则很简单:
>如果项目单独使用,则必须通过属性将其配置传递给它.
>如果某个项目由其父项包含,则必须通过parents属性将其配置传递给它
>我无法将完整的组合HTML写入index.html.它必须在运行中加载.他们是规则.但是,这样做可以解决问题.
> URL必须是动态的,并且父级必须能够传递此信息而不依赖于范围继承 – 父级可能不在那里.
>第三方网站无法告诉我在哪里使用JS指出这些.他们唯一的工具是index.html中的HTML.属性配置很好.
index.html的:
<div zoo feeding-time="8am" template-base="/templates"></div>
OR – index.html也可以是:gorilla可以明确指定attr值,因为它不是继承的
<div gorilla template-base-url="/templates"></div>
Zoo.html – 它将自己的配置传递给gorilla
<div gorilla template-base-url="{{templateBaseUrl}}"></div>
动物园directive.js
angular.module("app").directive("zoo", [function() { return { restrict: "A", scope: true, templateUrl: function(element, attrs) { // THIS ONE NEVER FAILS BECAUSE ITS NEVER INTERPOLATED var base = attrs.templateBaseUrl; return base "/zoo.html"; }, link: function(scope, element, attrs) { // its my job to give gorilla a templateURL in this case scope.templateBaseUrl = attrs.templateBaseUrl; } }; }]);
gorilla.html
angular.module("app").directive("gorilla", [function() { return { restrict: "A", scope: true, templateUrl: function(element, attrs) { // THIS ONLY FAILS WHEN INCLUDED BY ZOO.HTML // AND THEN, ONLY SOMETIMES. RACE CONDITION? PRIORITY? // DOES NOT FAIL WHEN INCLUDED BY INDEX.HTML DIRECTLY var base = attrs.templateBaseUrl; return base "/gorilla.html"; } }; }]);
这有效.有时.有时,tempateUrl方法使用文字{{templateBaseUrl}}.我只能跟踪它,只要看到当gorilla的templateUrl方法使用attrs.templateBaseUrl时,attrs.templateBaseUrl它还没有被插值.
因此,gorilla.link()在插入{{templateBaseUrl}}和kaboom之前运行. 404在“{{templateBaseUrl}} / gorilla.html”
我怎么能避免这个?
https://docs.angularjs.org/error/ $编译/ tpload?P0 = {{templateBaseUrl}} / gorilla.html
我在每个项目依赖的提供程序中都有这个baseUrl东西,但它与此简化版本具有相同的效果.它必须是解析订单问题.
解决方法:
为什么?
您的方法失败,因为templateUrl函数必须在控制器的“编译”阶段之前运行(如果您还没有编译模板,则无法编译模板).使用嵌套指令,首先运行所有编译函数,然后运行链接函数.我发现下面的图表可以作为“使用嵌套指令时运行时什么时候”的参考 – 它来自一个相当in depth article的主题 – 一个很好的阅读.
http://www.jvandemo.com/content/images/2014/Aug/cycle-2.png
考虑到这一点,很明显当你的gorilla指令正在编译时,动物园的链接功能还没有运行,这意味着范围值甚至没有被设置,更不用说内插到属性中了.
如何避免它
看起来你将不得不自己获取和编译模板.您可以使用angular的$templateRequest
来确保模板正确缓存.我们可以通过仅使用范围中的值来避免插值是否已经发生(我使用了隔离范围,因为它使事情变得不那么模糊,并且通常是更好的实践,但如果你想要,你可以只使用范围继承).
免责声明:以下代码是在没有运行的情况下编写的,肯定会包含拼写错误和错误!希望你会看到逻辑……
子指令代码:
angular.module("app").directive("gorilla", function($templateRequest, $compile) { return { restrict: "A", // set up an isolate scope scope: { tplBaseUrl: '=' }, link: { pre: function (scope, elem, attr) { // Decide if the url is directly set or is dynamic var baseUrl = scope.tplBaseUrl ? scope.tplBaseUrl : attr.tplBaseUrl; // request the template $templateRequest(baseUrl '/gorilla.html') .then(function (response) { tpl = response.data; // compile the html, then link it to the scope $elem = $compile(tpl)(scope); // append the compiled template inside the element elem.append($elem); }); }, post: function (scope, elem, attr){ // you can put your normal link function code in here. } } };});
请注意,预链接函数的第一行实质上是检查是否存在使用您传递的名称设置的范围变量,如果没有,则假定您已经为其指定了url字符串(因此使用属性值).这可能不是最好的方法 – 我很想使用两个不同的属性,但这取决于你.
重要的是(再次参考图表!),您的父(zoo)指令必须在其预链接函数中设置模板库的值,否则当子指令运行的链接函数运行时,该值将是未定义的.
(简体)父指令:
你可以在这里使用类似于child指令,或者使用你原来的方法.此代码已简化,以提供在预链接期间如何设置tplBaseUrl的示例.
angular.module("app").directive("zoo", function() { return { restrict: "A", template: '<div gorilla tpl-base-url="tplBaseUrl"></div>', link: { pre: function (scope, elem, attr) { // make sure it is set here! scope.tplBaseUrl = "/templates"; }, post: function (scope, elem, attr){ // link logic } } };});
最后,如果您要静态设置它,这也应该有效:
<div gorilla template-base-url="/templates"></div>
来源:https://www.icode9.com/content-1-263101.html
联系客服