ui-router: templateUrl 函数中的异步数据
ui-router: async data in templateUrl function
我 运行 遇到了一个 ui 路由器的新问题。我基本上是在尝试查询我的 API 模板 url,该模板作为 Resource
对象存储和 returned。问题是 templateUrl
函数似乎 returning 未定义。我的代码如下:
(function() {
'use strict';
angular.module('myApp')
.config(function ($stateProvider, PageProvider, $httpProvider) {
$stateProvider
.state('core', {
abstract: true,
templateUrl: 'app/core/core.index.html',
controller: 'CoreController',
controllerAs: 'vm'
})
/* Parent page view */
.state('core.page', {
url: '/:slug',
views: {
'page_content@core': {
templateUrl: function(params) {
var slug = params.slug;
// only need to load core template
var url = 'assets/templates/' + slug + '.html';
return url;
},
controller: 'PageController',
controllerAs: 'vm'
}
}
})
.state('core.page.child', {
url: '/:child',
views: {
'page_content@core': {
templateUrl: function($stateParams) {
PageProvider
.$get() // $get() returns Page service
.findOne($stateParams.child)
.$promise
.then(function(data){
return data.template.url;
});
}
}
}
});
});
})();
我为我的状态设置了一个断点,'core.page.child',以查看作用域中有哪些变量可用,我发现了一些奇怪的东西:ui
我真的不明白为什么会这样,因为 .then(cb)
仅在承诺解决后才被调用,这意味着它应该 return 正确的值如预期的那样 - 但它没有' t.
如有任何帮助,我们将不胜感激。
编辑:我应该补充一点,发生的事情是 ui-router 根本没有加载我的模板 - 我得到一个空的 ui-view
。我最初认为这可能是我的 $stateProvider
配置有问题,但事实并非如此。
Edit2:我根据调用堆栈深入研究了源代码。看来你们两个都是对的 - ui-router 不符合承诺。
/**
* @ngdoc function
* @name ui.router.util.$templateFactory#fromConfig
* @methodOf ui.router.util.$templateFactory
*
* @description
* Creates a template from a configuration object.
*
* @param {object} config Configuration object for which to load a template.
* The following properties are search in the specified order, and the first one
* that is defined is used to create the template:
*
* @param {string|object} config.template html string template or function to
* load via {@link ui.router.util.$templateFactory#fromString fromString}.
* @param {string|object} config.templateUrl url to load or a function returning
* the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}.
* @param {Function} config.templateProvider function to invoke via
* {@link ui.router.util.$templateFactory#fromProvider fromProvider}.
* @param {object} params Parameters to pass to the template function.
* @param {object} locals Locals to pass to `invoke` if the template is loaded
* via a `templateProvider`. Defaults to `{ params: params }`.
*
* @return {string|object} The template html as a string, or a promise for
* that string,or `null` if no template is configured.
*/
this.fromConfig = function (config, params, locals) {
return (
isDefined(config.template) ? this.fromString(config.template, params) :
isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) :
null
);
};
看来我要么使用 $stateProvider.decorator
,要么破解 ui-router 的核心。我想我可能只做后者并提交 PR。我也会将此问题发布到 github 存储库中,看看 ui-router 团队中是否有人有解决此问题的方法。
您可以使用 resolve
和 templateProvider
来完成此操作。
.state('child', {
url: '/:child',
resolve: {
childTemplate: function ($stateParams, $templateRequest) {
return $templateRequest($stateParams.child + ".html");
}
},
templateProvider: function(childTemplate) {
return childTemplate;
}
});
这创建了一个使用 $stateParams
获取模板的解析(我使用 $templateRequest
获取,添加到 $templateCache
,return内容合而为一)。然后,将解析后的模板内容注入到视图的templateProvider中。
我 运行 遇到了一个 ui 路由器的新问题。我基本上是在尝试查询我的 API 模板 url,该模板作为 Resource
对象存储和 returned。问题是 templateUrl
函数似乎 returning 未定义。我的代码如下:
(function() {
'use strict';
angular.module('myApp')
.config(function ($stateProvider, PageProvider, $httpProvider) {
$stateProvider
.state('core', {
abstract: true,
templateUrl: 'app/core/core.index.html',
controller: 'CoreController',
controllerAs: 'vm'
})
/* Parent page view */
.state('core.page', {
url: '/:slug',
views: {
'page_content@core': {
templateUrl: function(params) {
var slug = params.slug;
// only need to load core template
var url = 'assets/templates/' + slug + '.html';
return url;
},
controller: 'PageController',
controllerAs: 'vm'
}
}
})
.state('core.page.child', {
url: '/:child',
views: {
'page_content@core': {
templateUrl: function($stateParams) {
PageProvider
.$get() // $get() returns Page service
.findOne($stateParams.child)
.$promise
.then(function(data){
return data.template.url;
});
}
}
}
});
});
})();
我为我的状态设置了一个断点,'core.page.child',以查看作用域中有哪些变量可用,我发现了一些奇怪的东西:ui
我真的不明白为什么会这样,因为 .then(cb)
仅在承诺解决后才被调用,这意味着它应该 return 正确的值如预期的那样 - 但它没有' t.
如有任何帮助,我们将不胜感激。
编辑:我应该补充一点,发生的事情是 ui-router 根本没有加载我的模板 - 我得到一个空的 ui-view
。我最初认为这可能是我的 $stateProvider
配置有问题,但事实并非如此。
Edit2:我根据调用堆栈深入研究了源代码。看来你们两个都是对的 - ui-router 不符合承诺。
/**
* @ngdoc function
* @name ui.router.util.$templateFactory#fromConfig
* @methodOf ui.router.util.$templateFactory
*
* @description
* Creates a template from a configuration object.
*
* @param {object} config Configuration object for which to load a template.
* The following properties are search in the specified order, and the first one
* that is defined is used to create the template:
*
* @param {string|object} config.template html string template or function to
* load via {@link ui.router.util.$templateFactory#fromString fromString}.
* @param {string|object} config.templateUrl url to load or a function returning
* the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}.
* @param {Function} config.templateProvider function to invoke via
* {@link ui.router.util.$templateFactory#fromProvider fromProvider}.
* @param {object} params Parameters to pass to the template function.
* @param {object} locals Locals to pass to `invoke` if the template is loaded
* via a `templateProvider`. Defaults to `{ params: params }`.
*
* @return {string|object} The template html as a string, or a promise for
* that string,or `null` if no template is configured.
*/
this.fromConfig = function (config, params, locals) {
return (
isDefined(config.template) ? this.fromString(config.template, params) :
isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) :
null
);
};
看来我要么使用 $stateProvider.decorator
,要么破解 ui-router 的核心。我想我可能只做后者并提交 PR。我也会将此问题发布到 github 存储库中,看看 ui-router 团队中是否有人有解决此问题的方法。
您可以使用 resolve
和 templateProvider
来完成此操作。
.state('child', {
url: '/:child',
resolve: {
childTemplate: function ($stateParams, $templateRequest) {
return $templateRequest($stateParams.child + ".html");
}
},
templateProvider: function(childTemplate) {
return childTemplate;
}
});
这创建了一个使用 $stateParams
获取模板的解析(我使用 $templateRequest
获取,添加到 $templateCache
,return内容合而为一)。然后,将解析后的模板内容注入到视图的templateProvider中。