1 | /** @publicapi @module view */ /** */
|
2 | import { ng as angular } from './angular';
|
3 | import { isArray, isDefined, isFunction, isObject, services, tail, kebobString, unnestR, Resolvable, } from '@uirouter/core';
|
4 | /**
|
5 | * Service which manages loading of templates from a ViewConfig.
|
6 | */
|
7 | var TemplateFactory = /** @class */ (function () {
|
8 | function TemplateFactory() {
|
9 | var _this = this;
|
10 | /** @hidden */ this._useHttp = angular.version.minor < 3;
|
11 | /** @hidden */ this.$get = [
|
12 | '$http',
|
13 | '$templateCache',
|
14 | '$injector',
|
15 | function ($http, $templateCache, $injector) {
|
16 | _this.$templateRequest = $injector.has && $injector.has('$templateRequest') && $injector.get('$templateRequest');
|
17 | _this.$http = $http;
|
18 | _this.$templateCache = $templateCache;
|
19 | return _this;
|
20 | },
|
21 | ];
|
22 | }
|
23 | /** @hidden */
|
24 | TemplateFactory.prototype.useHttpService = function (value) {
|
25 | this._useHttp = value;
|
26 | };
|
27 | /**
|
28 | * Creates a template from a configuration object.
|
29 | *
|
30 | * @param config Configuration object for which to load a template.
|
31 | * The following properties are search in the specified order, and the first one
|
32 | * that is defined is used to create the template:
|
33 | *
|
34 | * @param params Parameters to pass to the template function.
|
35 | * @param context The resolve context associated with the template's view
|
36 | *
|
37 | * @return {string|object} The template html as a string, or a promise for
|
38 | * that string,or `null` if no template is configured.
|
39 | */
|
40 | TemplateFactory.prototype.fromConfig = function (config, params, context) {
|
41 | var defaultTemplate = '<ui-view></ui-view>';
|
42 | var asTemplate = function (result) { return services.$q.when(result).then(function (str) { return ({ template: str }); }); };
|
43 | var asComponent = function (result) { return services.$q.when(result).then(function (str) { return ({ component: str }); }); };
|
44 | return isDefined(config.template)
|
45 | ? asTemplate(this.fromString(config.template, params))
|
46 | : isDefined(config.templateUrl)
|
47 | ? asTemplate(this.fromUrl(config.templateUrl, params))
|
48 | : isDefined(config.templateProvider)
|
49 | ? asTemplate(this.fromProvider(config.templateProvider, params, context))
|
50 | : isDefined(config.component)
|
51 | ? asComponent(config.component)
|
52 | : isDefined(config.componentProvider)
|
53 | ? asComponent(this.fromComponentProvider(config.componentProvider, params, context))
|
54 | : asTemplate(defaultTemplate);
|
55 | };
|
56 | /**
|
57 | * Creates a template from a string or a function returning a string.
|
58 | *
|
59 | * @param template html template as a string or function that returns an html template as a string.
|
60 | * @param params Parameters to pass to the template function.
|
61 | *
|
62 | * @return {string|object} The template html as a string, or a promise for that
|
63 | * string.
|
64 | */
|
65 | TemplateFactory.prototype.fromString = function (template, params) {
|
66 | return isFunction(template) ? template(params) : template;
|
67 | };
|
68 | /**
|
69 | * Loads a template from the a URL via `$http` and `$templateCache`.
|
70 | *
|
71 | * @param {string|Function} url url of the template to load, or a function
|
72 | * that returns a url.
|
73 | * @param {Object} params Parameters to pass to the url function.
|
74 | * @return {string|Promise.<string>} The template html as a string, or a promise
|
75 | * for that string.
|
76 | */
|
77 | TemplateFactory.prototype.fromUrl = function (url, params) {
|
78 | if (isFunction(url))
|
79 | url = url(params);
|
80 | if (url == null)
|
81 | return null;
|
82 | if (this._useHttp) {
|
83 | return this.$http
|
84 | .get(url, { cache: this.$templateCache, headers: { Accept: 'text/html' } })
|
85 | .then(function (response) {
|
86 | return response.data;
|
87 | });
|
88 | }
|
89 | return this.$templateRequest(url);
|
90 | };
|
91 | /**
|
92 | * Creates a template by invoking an injectable provider function.
|
93 | *
|
94 | * @param provider Function to invoke via `locals`
|
95 | * @param {Function} injectFn a function used to invoke the template provider
|
96 | * @return {string|Promise.<string>} The template html as a string, or a promise
|
97 | * for that string.
|
98 | */
|
99 | TemplateFactory.prototype.fromProvider = function (provider, params, context) {
|
100 | var deps = services.$injector.annotate(provider);
|
101 | var providerFn = isArray(provider) ? tail(provider) : provider;
|
102 | var resolvable = new Resolvable('', providerFn, deps);
|
103 | return resolvable.get(context);
|
104 | };
|
105 | /**
|
106 | * Creates a component's template by invoking an injectable provider function.
|
107 | *
|
108 | * @param provider Function to invoke via `locals`
|
109 | * @param {Function} injectFn a function used to invoke the template provider
|
110 | * @return {string} The template html as a string: "<component-name input1='::$resolve.foo'></component-name>".
|
111 | */
|
112 | TemplateFactory.prototype.fromComponentProvider = function (provider, params, context) {
|
113 | var deps = services.$injector.annotate(provider);
|
114 | var providerFn = isArray(provider) ? tail(provider) : provider;
|
115 | var resolvable = new Resolvable('', providerFn, deps);
|
116 | return resolvable.get(context);
|
117 | };
|
118 | /**
|
119 | * Creates a template from a component's name
|
120 | *
|
121 | * This implements route-to-component.
|
122 | * It works by retrieving the component (directive) metadata from the injector.
|
123 | * It analyses the component's bindings, then constructs a template that instantiates the component.
|
124 | * The template wires input and output bindings to resolves or from the parent component.
|
125 | *
|
126 | * @param uiView {object} The parent ui-view (for binding outputs to callbacks)
|
127 | * @param context The ResolveContext (for binding outputs to callbacks returned from resolves)
|
128 | * @param component {string} Component's name in camel case.
|
129 | * @param bindings An object defining the component's bindings: {foo: '<'}
|
130 | * @return {string} The template as a string: "<component-name input1='::$resolve.foo'></component-name>".
|
131 | */
|
132 | TemplateFactory.prototype.makeComponentTemplate = function (uiView, context, component, bindings) {
|
133 | bindings = bindings || {};
|
134 | // Bind once prefix
|
135 | var prefix = angular.version.minor >= 3 ? '::' : '';
|
136 | // Convert to kebob name. Add x- prefix if the string starts with `x-` or `data-`
|
137 | var kebob = function (camelCase) {
|
138 | var kebobed = kebobString(camelCase);
|
139 | return /^(x|data)-/.exec(kebobed) ? "x-" + kebobed : kebobed;
|
140 | };
|
141 | var attributeTpl = function (input) {
|
142 | var name = input.name, type = input.type;
|
143 | var attrName = kebob(name);
|
144 | // If the ui-view has an attribute which matches a binding on the routed component
|
145 | // then pass that attribute through to the routed component template.
|
146 | // Prefer ui-view wired mappings to resolve data, unless the resolve was explicitly bound using `bindings:`
|
147 | if (uiView.attr(attrName) && !bindings[name])
|
148 | return attrName + "='" + uiView.attr(attrName) + "'";
|
149 | var resolveName = bindings[name] || name;
|
150 | // Pre-evaluate the expression for "@" bindings by enclosing in {{ }}
|
151 | // some-attr="{{ ::$resolve.someResolveName }}"
|
152 | if (type === '@')
|
153 | return attrName + "='{{" + prefix + "$resolve." + resolveName + "}}'";
|
154 | // Wire "&" callbacks to resolves that return a callback function
|
155 | // Get the result of the resolve (should be a function) and annotate it to get its arguments.
|
156 | // some-attr="$resolve.someResolveResultName(foo, bar)"
|
157 | if (type === '&') {
|
158 | var res = context.getResolvable(resolveName);
|
159 | var fn = res && res.data;
|
160 | var args = (fn && services.$injector.annotate(fn)) || [];
|
161 | // account for array style injection, i.e., ['foo', function(foo) {}]
|
162 | var arrayIdxStr = isArray(fn) ? "[" + (fn.length - 1) + "]" : '';
|
163 | return attrName + "='$resolve." + resolveName + arrayIdxStr + "(" + args.join(',') + ")'";
|
164 | }
|
165 | // some-attr="::$resolve.someResolveName"
|
166 | return attrName + "='" + prefix + "$resolve." + resolveName + "'";
|
167 | };
|
168 | var attrs = getComponentBindings(component).map(attributeTpl).join(' ');
|
169 | var kebobName = kebob(component);
|
170 | return "<" + kebobName + " " + attrs + "></" + kebobName + ">";
|
171 | };
|
172 | return TemplateFactory;
|
173 | }());
|
174 | export { TemplateFactory };
|
175 | // Gets all the directive(s)' inputs ('@', '=', and '<') and outputs ('&')
|
176 | function getComponentBindings(name) {
|
177 | var cmpDefs = services.$injector.get(name + 'Directive'); // could be multiple
|
178 | if (!cmpDefs || !cmpDefs.length)
|
179 | throw new Error("Unable to find component named '" + name + "'");
|
180 | return cmpDefs.map(getBindings).reduce(unnestR, []);
|
181 | }
|
182 | // Given a directive definition, find its object input attributes
|
183 | // Use different properties, depending on the type of directive (component, bindToController, normal)
|
184 | var getBindings = function (def) {
|
185 | if (isObject(def.bindToController))
|
186 | return scopeBindings(def.bindToController);
|
187 | return scopeBindings(def.scope);
|
188 | };
|
189 | // for ng 1.2 style, process the scope: { input: "=foo" }
|
190 | // for ng 1.3 through ng 1.5, process the component's bindToController: { input: "=foo" } object
|
191 | var scopeBindings = function (bindingsObj) {
|
192 | return Object.keys(bindingsObj || {})
|
193 | // [ 'input', [ '=foo', '=', 'foo' ] ]
|
194 | .map(function (key) { return [key, /^([=<@&])[?]?(.*)/.exec(bindingsObj[key])]; })
|
195 | // skip malformed values
|
196 | .filter(function (tuple) { return isDefined(tuple) && isArray(tuple[1]); })
|
197 | // { name: ('foo' || 'input'), type: '=' }
|
198 | .map(function (tuple) { return ({ name: tuple[1][2] || tuple[0], type: tuple[1][1] }); });
|
199 | };
|
200 | //# sourceMappingURL=templateFactory.js.map |
\ | No newline at end of file |