我希望能够从promise
加载指令的模板。 e.g。
template: templateRepo.get('myTemplate')
templateRepo.get
返回一个promise,当解析时,该字符串中包含模板的内容。
有什么想法吗?
答案 0 :(得分:13)
你可以在你的指令中加载你的html,将它应用到你的元素并编译。
.directive('myDirective', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
//Some arbitrary promise.
fetchHtml()
.then(function(result){
element.html(result);
$compile(element.contents())(scope);
}, function(error){
});
}
}
});
答案 1 :(得分:2)
这是一个非常有趣的问题,有几个不同复杂性的答案。正如其他人已经建议的那样,您可以将加载图像放在指令中,当模板加载时,它将被替换。
看到你想要更适合其他事情的通用加载指标解决方案,我建议:
这是一个非常简单的示例,您可以从以下开始:
<button ng-click="more()">more</button>
<div test="item" ng-repeat="item in items"></div>
.throbber {
position: absolute;
top: calc(50% - 16px);
left: calc(50% - 16px);
}
angular
.module("app", [])
.run(function ($rootScope) {
$rootScope.items = ["One", "Two"];
$rootScope.more = function () {
$rootScope.items.push(Math.random());
};
})
.factory("throbber", function () {
var visible = false;
var throbber = document.createElement("img");
throbber.src = "http://upload.wikimedia.org/wikipedia/en/2/29/Throbber-Loadinfo-292929-ffffff.gif";
throbber.classList.add("throbber");
function show () {
document.body.appendChild(throbber);
}
function hide () {
document.body.removeChild(throbber);
}
return {
show: show,
hide: hide
};
})
.directive("test", function ($templateCache, $timeout, $compile, $q, throbber) {
var template = "<div>{{text}}</div>";
var templateUrl = "templateUrl";
return {
link: function (scope, el, attr) {
var tmpl = $templateCache.get(templateUrl);
if (!tmpl) {
throbber.show();
tmpl = $timeout(function () {
return template;
}, 1000);
}
$q.when(tmpl).then(function (value) {
$templateCache.put(templateUrl, value);
el.html(value);
$compile(el.contents())(scope);
throbber.hide();
});
},
scope: {
text: "=test"
}
};
});
在实时代码中,您必须将$timeout
替换为$http.get(templateUrl)
,我使用前者来说明异步加载。
模板加载如何在我的示例中起作用:
$templateCache
中是否有我们的模板。[$compile][2]
。如果您想知道$templateCache
是什么,read the docs。 AngularJS默认使用templateUrl
,所以我做了同样的事情。
模板加载可能会移动到装饰器,但我缺乏相关的经验。这将进一步分离关注点,因为指令不需要知道指标,并摆脱样板代码。
我还添加了ng-repeat
和run
内容,以证明模板如果已经加载则不会触发指示符。
答案 2 :(得分:0)
我要做的是在我的指令中添加ng-include以有选择地加载我需要的内容
从角度页面检查此演示。它可能有所帮助:
答案 3 :(得分:-1)
````
/**
* async load template
* eg :
* <div class="ui-header">
* {{data.name}}
* <ng-transclude></ng-transclude>
* </div>
*/
Spa.Service.factory("RequireTpl", [
'$q',
'$templateCache',
'DataRequest',
'TplConfig',
function(
$q,
$templateCache,
DataRequest,
TplConfig
) {
function getTemplate(tplName) {
var name = TplConfig[tplName];
var tpl = "";
if(!name) {
return $q.reject(tpl);
} else {
tpl = $templateCache.get(name) || "";
}
if(!!tpl) {
return $q.resolve(tpl);
}
//加载还未获得的模板
return new $q(function(resolve, reject) {
DataRequest.get({
url : "/template/",
action : "components",
responseType : "text",
components : name
}).success(function(tpl) {
$templateCache.put(name, tpl);
resolve(tpl);
}).error(function() {
reject(null);
});
});
}
return getTemplate;
}]);
/**
* usage:
* <component template="table" data="info">
* <span>{{info.name}}{{name}}</span>
* </component>
*/
Spa.Directive.directive("component", [
"$compile",
"RequireTpl",
function(
$compile,
RequireTpl
) {
var directive = {
restrict : 'E',
scope : {
data : '='
},
transclude : true,
link: function ($scope, element, attrs, $controller, $transclude) {
var linkFn = $compile(element.contents());
element.empty();
var tpl = attrs.template || "";
RequireTpl(tpl)
.then(function(rs) {
var tplElem = angular.element(rs);
element.replaceWith(tplElem);
$transclude(function(clone, transcludedScope) {
if(clone.length) {
tplElem.find("ng-transclude").replaceWith(clone);
linkFn($scope);
} else {
transcludedScope.$destroy()
}
$compile(tplElem.contents())($scope);
}, null, "");
})
.catch(function() {
element.remove();
console.log("%c component tpl isn't exist : " + tpl, "color:red")
});
}
};
return directive;
}]);
````