@sitecore-jss/sitecore-jss-angular 18.0.2-canary.0 → 18.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundles/sitecore-jss-sitecore-jss-angular.umd.js +1421 -1421
- package/dist/components/date.directive.d.ts +17 -17
- package/dist/components/file.directive.d.ts +14 -14
- package/dist/components/generic-link.directive.d.ts +14 -14
- package/dist/components/image.directive.d.ts +28 -28
- package/dist/components/link.directive.d.ts +18 -18
- package/dist/components/missing-component.component.d.ts +3 -3
- package/dist/components/placeholder-loading.directive.d.ts +5 -5
- package/dist/components/placeholder.component.d.ts +45 -45
- package/dist/components/placeholder.token.d.ts +30 -30
- package/dist/components/raw.component.d.ts +9 -9
- package/dist/components/render-component.component.d.ts +29 -29
- package/dist/components/render-each.directive.d.ts +5 -5
- package/dist/components/render-empty.directive.d.ts +5 -5
- package/dist/components/rendering-field.d.ts +20 -20
- package/dist/components/rendering.d.ts +5 -5
- package/dist/components/rich-text.directive.d.ts +12 -12
- package/dist/components/router-link.directive.d.ts +12 -12
- package/dist/components/text.directive.d.ts +13 -13
- package/dist/esm2015/components/date.directive.js +52 -52
- package/dist/esm2015/components/file.directive.js +42 -42
- package/dist/esm2015/components/generic-link.directive.js +57 -57
- package/dist/esm2015/components/image.directive.js +122 -122
- package/dist/esm2015/components/link.directive.js +98 -98
- package/dist/esm2015/components/missing-component.component.js +12 -12
- package/dist/esm2015/components/placeholder-loading.directive.js +14 -14
- package/dist/esm2015/components/placeholder.component.js +191 -191
- package/dist/esm2015/components/placeholder.token.js +20 -20
- package/dist/esm2015/components/raw.component.js +36 -36
- package/dist/esm2015/components/render-component.component.js +88 -88
- package/dist/esm2015/components/render-each.directive.js +14 -14
- package/dist/esm2015/components/render-empty.directive.js +14 -14
- package/dist/esm2015/components/rendering-field.js +1 -1
- package/dist/esm2015/components/rendering.js +7 -7
- package/dist/esm2015/components/rich-text.directive.js +40 -40
- package/dist/esm2015/components/router-link.directive.js +43 -43
- package/dist/esm2015/components/text.directive.js +53 -53
- package/dist/esm2015/jss-component-factory.service.js +86 -86
- package/dist/esm2015/layout-service-error.js +2 -2
- package/dist/esm2015/layout.service.js +28 -28
- package/dist/esm2015/lib.module.js +111 -111
- package/dist/esm2015/public_api.js +16 -16
- package/dist/esm2015/sitecore-jss-sitecore-jss-angular.js +12 -12
- package/dist/esm2015/utils.js +37 -37
- package/dist/fesm2015/sitecore-jss-sitecore-jss-angular.js +1079 -1079
- package/dist/jss-component-factory.service.d.ts +21 -21
- package/dist/layout-service-error.d.ts +8 -8
- package/dist/layout.service.d.ts +8 -8
- package/dist/lib.module.d.ts +24 -24
- package/dist/package.json +2 -2
- package/dist/public_api.d.ts +17 -17
- package/dist/sitecore-jss-sitecore-jss-angular.d.ts +12 -12
- package/dist/utils.d.ts +10 -10
- package/package.json +3 -3
|
@@ -7,919 +7,919 @@ import { Observable, throwError, from } from 'rxjs';
|
|
|
7
7
|
import { takeWhile, catchError } from 'rxjs/operators';
|
|
8
8
|
import { DatePipe, CommonModule } from '@angular/common';
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* File fields cannot be managed via the EE. We never output "editable."
|
|
12
|
-
*/
|
|
13
|
-
class FileDirective {
|
|
14
|
-
constructor(viewContainer, templateRef) {
|
|
15
|
-
this.viewContainer = viewContainer;
|
|
16
|
-
this.templateRef = templateRef;
|
|
17
|
-
}
|
|
18
|
-
ngOnChanges(changes) {
|
|
19
|
-
if (changes.field) {
|
|
20
|
-
if (!this.viewRef) {
|
|
21
|
-
this.viewContainer.clear();
|
|
22
|
-
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
23
|
-
}
|
|
24
|
-
this.updateView();
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
updateView() {
|
|
28
|
-
const field = this.field;
|
|
29
|
-
if (!field || (!field.value && !field.src)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const file = field.src ? field : field.value;
|
|
33
|
-
this.viewRef.rootNodes.forEach((node) => {
|
|
34
|
-
node.href = file.src;
|
|
35
|
-
if (node.innerHTML === '') {
|
|
36
|
-
node.innerHTML = file.title || file.displayName;
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
FileDirective.decorators = [
|
|
42
|
-
{ type: Directive, args: [{ selector: '[scFile]' },] }
|
|
43
|
-
];
|
|
44
|
-
FileDirective.ctorParameters = () => [
|
|
45
|
-
{ type: ViewContainerRef },
|
|
46
|
-
{ type: TemplateRef }
|
|
47
|
-
];
|
|
48
|
-
FileDirective.propDecorators = {
|
|
49
|
-
field: [{ type: Input, args: ['scFile',] }]
|
|
10
|
+
/**
|
|
11
|
+
* File fields cannot be managed via the EE. We never output "editable."
|
|
12
|
+
*/
|
|
13
|
+
class FileDirective {
|
|
14
|
+
constructor(viewContainer, templateRef) {
|
|
15
|
+
this.viewContainer = viewContainer;
|
|
16
|
+
this.templateRef = templateRef;
|
|
17
|
+
}
|
|
18
|
+
ngOnChanges(changes) {
|
|
19
|
+
if (changes.field) {
|
|
20
|
+
if (!this.viewRef) {
|
|
21
|
+
this.viewContainer.clear();
|
|
22
|
+
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
23
|
+
}
|
|
24
|
+
this.updateView();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
updateView() {
|
|
28
|
+
const field = this.field;
|
|
29
|
+
if (!field || (!field.value && !field.src)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const file = field.src ? field : field.value;
|
|
33
|
+
this.viewRef.rootNodes.forEach((node) => {
|
|
34
|
+
node.href = file.src;
|
|
35
|
+
if (node.innerHTML === '') {
|
|
36
|
+
node.innerHTML = file.title || file.displayName;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
FileDirective.decorators = [
|
|
42
|
+
{ type: Directive, args: [{ selector: '[scFile]' },] }
|
|
43
|
+
];
|
|
44
|
+
FileDirective.ctorParameters = () => [
|
|
45
|
+
{ type: ViewContainerRef },
|
|
46
|
+
{ type: TemplateRef }
|
|
47
|
+
];
|
|
48
|
+
FileDirective.propDecorators = {
|
|
49
|
+
field: [{ type: Input, args: ['scFile',] }]
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
class ImageDirective {
|
|
53
|
-
constructor(viewContainer, templateRef, renderer, elementRef) {
|
|
54
|
-
this.viewContainer = viewContainer;
|
|
55
|
-
this.templateRef = templateRef;
|
|
56
|
-
this.renderer = renderer;
|
|
57
|
-
this.elementRef = elementRef;
|
|
58
|
-
this.inlineRef = null;
|
|
59
|
-
this.editable = true;
|
|
60
|
-
this.urlParams = {};
|
|
61
|
-
this.attrs = {};
|
|
62
|
-
}
|
|
63
|
-
ngOnChanges(changes) {
|
|
64
|
-
if (changes.field || changes.editable || changes.urlParams || changes.attrs) {
|
|
65
|
-
this.viewContainer.clear();
|
|
66
|
-
if (this.inlineRef) {
|
|
67
|
-
this.inlineRef.remove();
|
|
68
|
-
this.inlineRef = null;
|
|
69
|
-
}
|
|
70
|
-
this.updateView();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
updateView() {
|
|
74
|
-
const overrideAttrs = Object.assign(Object.assign({}, this.getElementAttrs()), this.attrs);
|
|
75
|
-
const media = this.field;
|
|
76
|
-
if (!media || (!media.editable && !media.value && !media.src)) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
let attrs = {};
|
|
80
|
-
// we likely have an experience editor value, should be a string
|
|
81
|
-
if (this.editable && media.editable) {
|
|
82
|
-
const foundImg = mediaApi.findEditorImageTag(media.editable);
|
|
83
|
-
if (!foundImg) {
|
|
84
|
-
return this.renderInlineWrapper(media.editable);
|
|
85
|
-
}
|
|
86
|
-
attrs = this.getImageAttrs(foundImg.attrs, overrideAttrs, this.urlParams);
|
|
87
|
-
if (!attrs) {
|
|
88
|
-
return this.renderInlineWrapper(media.editable);
|
|
89
|
-
}
|
|
90
|
-
const tempImg = this.renderer.createElement('img');
|
|
91
|
-
Object.entries(attrs).forEach(([key, attrValue]) => tempImg.setAttribute(key, attrValue));
|
|
92
|
-
const editableMarkup = media.editable.replace(foundImg.imgTag, tempImg.outerHTML);
|
|
93
|
-
return this.renderInlineWrapper(editableMarkup);
|
|
94
|
-
}
|
|
95
|
-
// some wise-guy/gal is passing in a 'raw' image object value
|
|
96
|
-
const img = media.src ? media : media.value;
|
|
97
|
-
if (!img) {
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
attrs = this.getImageAttrs(img, overrideAttrs, this.urlParams);
|
|
101
|
-
if (attrs) {
|
|
102
|
-
this.renderTemplate(attrs);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
getImageAttrs(fieldAttrs, parsedAttrs, imageParams) {
|
|
106
|
-
const combinedAttrs = Object.assign(Object.assign({}, fieldAttrs), parsedAttrs);
|
|
107
|
-
// eslint-disable-next-line prefer-const
|
|
108
|
-
let { src, srcSet } = combinedAttrs, otherAttrs = __rest(combinedAttrs, ["src", "srcSet"]);
|
|
109
|
-
if (!src) {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
const newAttrs = Object.assign({}, otherAttrs);
|
|
113
|
-
// update image URL for jss handler and image rendering params
|
|
114
|
-
src = mediaApi.updateImageUrl(src, imageParams, this.mediaUrlPrefix);
|
|
115
|
-
if (srcSet) {
|
|
116
|
-
// replace with HTML-formatted srcset, including updated image URLs
|
|
117
|
-
newAttrs.srcSet = mediaApi.getSrcSet(src, srcSet, imageParams, this.mediaUrlPrefix);
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
newAttrs.src = src;
|
|
121
|
-
}
|
|
122
|
-
return newAttrs;
|
|
123
|
-
}
|
|
124
|
-
renderTemplate(imageProps) {
|
|
125
|
-
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
126
|
-
viewRef.rootNodes.forEach((node) => {
|
|
127
|
-
Object.entries(imageProps).forEach(([key, imgPropVal]) => this.renderer.setAttribute(node, key, imgPropVal));
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
getElementAttrs() {
|
|
131
|
-
const view = this.templateRef.createEmbeddedView(null);
|
|
132
|
-
const element = view.rootNodes[0];
|
|
133
|
-
if (!element) {
|
|
134
|
-
return {};
|
|
135
|
-
}
|
|
136
|
-
const attrs = {};
|
|
137
|
-
for (let i = 0; i < element.attributes.length; i++) {
|
|
138
|
-
const attr = element.attributes.item(i);
|
|
139
|
-
if (attr) {
|
|
140
|
-
attrs[attr.name] = attr.value;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return attrs;
|
|
144
|
-
}
|
|
145
|
-
renderInlineWrapper(editable) {
|
|
146
|
-
const span = this.renderer.createElement('span');
|
|
147
|
-
span.className = 'sc-image-wrapper';
|
|
148
|
-
span.innerHTML = editable;
|
|
149
|
-
const parentNode = this.renderer.parentNode(this.elementRef.nativeElement);
|
|
150
|
-
this.renderer.insertBefore(parentNode, span, this.elementRef.nativeElement);
|
|
151
|
-
parentNode.removeChild(this.elementRef.nativeElement);
|
|
152
|
-
this.inlineRef = span;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
ImageDirective.decorators = [
|
|
156
|
-
{ type: Directive, args: [{ selector: '[scImage]' },] }
|
|
157
|
-
];
|
|
158
|
-
ImageDirective.ctorParameters = () => [
|
|
159
|
-
{ type: ViewContainerRef },
|
|
160
|
-
{ type: TemplateRef },
|
|
161
|
-
{ type: Renderer2 },
|
|
162
|
-
{ type: ElementRef }
|
|
163
|
-
];
|
|
164
|
-
ImageDirective.propDecorators = {
|
|
165
|
-
field: [{ type: Input, args: ['scImage',] }],
|
|
166
|
-
editable: [{ type: Input, args: ['scImageEditable',] }],
|
|
167
|
-
mediaUrlPrefix: [{ type: Input, args: ['scImageMediaUrlPrefix',] }],
|
|
168
|
-
urlParams: [{ type: Input, args: ['scImageUrlParams',] }],
|
|
169
|
-
attrs: [{ type: Input, args: ['scImageAttrs',] }]
|
|
52
|
+
class ImageDirective {
|
|
53
|
+
constructor(viewContainer, templateRef, renderer, elementRef) {
|
|
54
|
+
this.viewContainer = viewContainer;
|
|
55
|
+
this.templateRef = templateRef;
|
|
56
|
+
this.renderer = renderer;
|
|
57
|
+
this.elementRef = elementRef;
|
|
58
|
+
this.inlineRef = null;
|
|
59
|
+
this.editable = true;
|
|
60
|
+
this.urlParams = {};
|
|
61
|
+
this.attrs = {};
|
|
62
|
+
}
|
|
63
|
+
ngOnChanges(changes) {
|
|
64
|
+
if (changes.field || changes.editable || changes.urlParams || changes.attrs) {
|
|
65
|
+
this.viewContainer.clear();
|
|
66
|
+
if (this.inlineRef) {
|
|
67
|
+
this.inlineRef.remove();
|
|
68
|
+
this.inlineRef = null;
|
|
69
|
+
}
|
|
70
|
+
this.updateView();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
updateView() {
|
|
74
|
+
const overrideAttrs = Object.assign(Object.assign({}, this.getElementAttrs()), this.attrs);
|
|
75
|
+
const media = this.field;
|
|
76
|
+
if (!media || (!media.editable && !media.value && !media.src)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let attrs = {};
|
|
80
|
+
// we likely have an experience editor value, should be a string
|
|
81
|
+
if (this.editable && media.editable) {
|
|
82
|
+
const foundImg = mediaApi.findEditorImageTag(media.editable);
|
|
83
|
+
if (!foundImg) {
|
|
84
|
+
return this.renderInlineWrapper(media.editable);
|
|
85
|
+
}
|
|
86
|
+
attrs = this.getImageAttrs(foundImg.attrs, overrideAttrs, this.urlParams);
|
|
87
|
+
if (!attrs) {
|
|
88
|
+
return this.renderInlineWrapper(media.editable);
|
|
89
|
+
}
|
|
90
|
+
const tempImg = this.renderer.createElement('img');
|
|
91
|
+
Object.entries(attrs).forEach(([key, attrValue]) => tempImg.setAttribute(key, attrValue));
|
|
92
|
+
const editableMarkup = media.editable.replace(foundImg.imgTag, tempImg.outerHTML);
|
|
93
|
+
return this.renderInlineWrapper(editableMarkup);
|
|
94
|
+
}
|
|
95
|
+
// some wise-guy/gal is passing in a 'raw' image object value
|
|
96
|
+
const img = media.src ? media : media.value;
|
|
97
|
+
if (!img) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
attrs = this.getImageAttrs(img, overrideAttrs, this.urlParams);
|
|
101
|
+
if (attrs) {
|
|
102
|
+
this.renderTemplate(attrs);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
getImageAttrs(fieldAttrs, parsedAttrs, imageParams) {
|
|
106
|
+
const combinedAttrs = Object.assign(Object.assign({}, fieldAttrs), parsedAttrs);
|
|
107
|
+
// eslint-disable-next-line prefer-const
|
|
108
|
+
let { src, srcSet } = combinedAttrs, otherAttrs = __rest(combinedAttrs, ["src", "srcSet"]);
|
|
109
|
+
if (!src) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const newAttrs = Object.assign({}, otherAttrs);
|
|
113
|
+
// update image URL for jss handler and image rendering params
|
|
114
|
+
src = mediaApi.updateImageUrl(src, imageParams, this.mediaUrlPrefix);
|
|
115
|
+
if (srcSet) {
|
|
116
|
+
// replace with HTML-formatted srcset, including updated image URLs
|
|
117
|
+
newAttrs.srcSet = mediaApi.getSrcSet(src, srcSet, imageParams, this.mediaUrlPrefix);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
newAttrs.src = src;
|
|
121
|
+
}
|
|
122
|
+
return newAttrs;
|
|
123
|
+
}
|
|
124
|
+
renderTemplate(imageProps) {
|
|
125
|
+
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
126
|
+
viewRef.rootNodes.forEach((node) => {
|
|
127
|
+
Object.entries(imageProps).forEach(([key, imgPropVal]) => this.renderer.setAttribute(node, key, imgPropVal));
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
getElementAttrs() {
|
|
131
|
+
const view = this.templateRef.createEmbeddedView(null);
|
|
132
|
+
const element = view.rootNodes[0];
|
|
133
|
+
if (!element) {
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
const attrs = {};
|
|
137
|
+
for (let i = 0; i < element.attributes.length; i++) {
|
|
138
|
+
const attr = element.attributes.item(i);
|
|
139
|
+
if (attr) {
|
|
140
|
+
attrs[attr.name] = attr.value;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return attrs;
|
|
144
|
+
}
|
|
145
|
+
renderInlineWrapper(editable) {
|
|
146
|
+
const span = this.renderer.createElement('span');
|
|
147
|
+
span.className = 'sc-image-wrapper';
|
|
148
|
+
span.innerHTML = editable;
|
|
149
|
+
const parentNode = this.renderer.parentNode(this.elementRef.nativeElement);
|
|
150
|
+
this.renderer.insertBefore(parentNode, span, this.elementRef.nativeElement);
|
|
151
|
+
parentNode.removeChild(this.elementRef.nativeElement);
|
|
152
|
+
this.inlineRef = span;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
ImageDirective.decorators = [
|
|
156
|
+
{ type: Directive, args: [{ selector: '[scImage]' },] }
|
|
157
|
+
];
|
|
158
|
+
ImageDirective.ctorParameters = () => [
|
|
159
|
+
{ type: ViewContainerRef },
|
|
160
|
+
{ type: TemplateRef },
|
|
161
|
+
{ type: Renderer2 },
|
|
162
|
+
{ type: ElementRef }
|
|
163
|
+
];
|
|
164
|
+
ImageDirective.propDecorators = {
|
|
165
|
+
field: [{ type: Input, args: ['scImage',] }],
|
|
166
|
+
editable: [{ type: Input, args: ['scImageEditable',] }],
|
|
167
|
+
mediaUrlPrefix: [{ type: Input, args: ['scImageMediaUrlPrefix',] }],
|
|
168
|
+
urlParams: [{ type: Input, args: ['scImageUrlParams',] }],
|
|
169
|
+
attrs: [{ type: Input, args: ['scImageAttrs',] }]
|
|
170
170
|
};
|
|
171
171
|
|
|
172
|
-
class LinkDirective {
|
|
173
|
-
constructor(viewContainer, templateRef, renderer, elementRef) {
|
|
174
|
-
this.viewContainer = viewContainer;
|
|
175
|
-
this.templateRef = templateRef;
|
|
176
|
-
this.renderer = renderer;
|
|
177
|
-
this.elementRef = elementRef;
|
|
178
|
-
this.inlineRef = null;
|
|
179
|
-
this.editable = true;
|
|
180
|
-
this.attrs = {};
|
|
181
|
-
}
|
|
182
|
-
ngOnChanges(changes) {
|
|
183
|
-
if (changes.field || changes.editable || changes.attrs) {
|
|
184
|
-
this.viewContainer.clear();
|
|
185
|
-
if (this.inlineRef) {
|
|
186
|
-
this.inlineRef.remove();
|
|
187
|
-
this.inlineRef = null;
|
|
188
|
-
}
|
|
189
|
-
this.updateView();
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
updateView() {
|
|
193
|
-
const field = this.field;
|
|
194
|
-
if (this.editable && field && field.editableFirstPart && field.editableLastPart) {
|
|
195
|
-
this.renderInlineWrapper(field.editableFirstPart, field.editableLastPart);
|
|
196
|
-
}
|
|
197
|
-
else if (field && (field.href || field.value)) {
|
|
198
|
-
const props = field.href ? field : field.value;
|
|
199
|
-
const linkText = field.text || field.value.text || field.href || field.value.href;
|
|
200
|
-
const mergedAttrs = Object.assign(Object.assign({}, props), this.attrs);
|
|
201
|
-
this.renderTemplate(mergedAttrs, linkText);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
renderTemplate(props, linkText) {
|
|
205
|
-
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
206
|
-
viewRef.rootNodes.forEach((node) => {
|
|
207
|
-
Object.entries(props).forEach(([key, propValue]) => {
|
|
208
|
-
if (key === 'href') {
|
|
209
|
-
const isInvalidLink = !propValue || /^https?:\/\/$/.test(propValue);
|
|
210
|
-
if (isInvalidLink) {
|
|
211
|
-
if (!node.href) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
propValue = node.href;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
if (key === 'class' && node.className) {
|
|
218
|
-
propValue += ` ${node.className}`;
|
|
219
|
-
}
|
|
220
|
-
this.renderer.setAttribute(node, key, propValue);
|
|
221
|
-
});
|
|
222
|
-
if (node.childNodes && node.childNodes.length === 0 && linkText) {
|
|
223
|
-
node.textContent = linkText;
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
renderInlineWrapper(editableFirstPart, editableLastPart) {
|
|
228
|
-
const span = this.renderer.createElement('span');
|
|
229
|
-
span.className = 'sc-link-wrapper';
|
|
230
|
-
span.innerHTML = editableFirstPart + editableLastPart;
|
|
231
|
-
// assign attributes from template to inline wrapper
|
|
232
|
-
const attrs = Object.assign(Object.assign({}, this.getElementAttrs()), this.attrs);
|
|
233
|
-
Object.entries(attrs).forEach(([key, attrValue]) => this.renderer.setAttribute(span, key, attrValue));
|
|
234
|
-
this.viewContainer.createEmbeddedView(this.templateRef);
|
|
235
|
-
const parentNode = this.renderer.parentNode(this.elementRef.nativeElement);
|
|
236
|
-
this.renderer.insertBefore(parentNode, span, this.elementRef.nativeElement);
|
|
237
|
-
this.inlineRef = span;
|
|
238
|
-
}
|
|
239
|
-
getElementAttrs() {
|
|
240
|
-
const view = this.templateRef.createEmbeddedView(null);
|
|
241
|
-
const element = view.rootNodes[0];
|
|
242
|
-
if (!element) {
|
|
243
|
-
return {};
|
|
244
|
-
}
|
|
245
|
-
const attrs = {};
|
|
246
|
-
for (let i = 0; i < element.attributes.length; i++) {
|
|
247
|
-
const attr = element.attributes.item(i);
|
|
248
|
-
if (attr) {
|
|
249
|
-
attrs[attr.name] = attr.value;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return attrs;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
LinkDirective.decorators = [
|
|
256
|
-
{ type: Directive, args: [{ selector: '[scLink]' },] }
|
|
257
|
-
];
|
|
258
|
-
LinkDirective.ctorParameters = () => [
|
|
259
|
-
{ type: ViewContainerRef },
|
|
260
|
-
{ type: TemplateRef },
|
|
261
|
-
{ type: Renderer2 },
|
|
262
|
-
{ type: ElementRef }
|
|
263
|
-
];
|
|
264
|
-
LinkDirective.propDecorators = {
|
|
265
|
-
editable: [{ type: Input, args: ['scLinkEditable',] }],
|
|
266
|
-
attrs: [{ type: Input, args: ['scLinkAttrs',] }],
|
|
267
|
-
field: [{ type: Input, args: ['scLink',] }]
|
|
172
|
+
class LinkDirective {
|
|
173
|
+
constructor(viewContainer, templateRef, renderer, elementRef) {
|
|
174
|
+
this.viewContainer = viewContainer;
|
|
175
|
+
this.templateRef = templateRef;
|
|
176
|
+
this.renderer = renderer;
|
|
177
|
+
this.elementRef = elementRef;
|
|
178
|
+
this.inlineRef = null;
|
|
179
|
+
this.editable = true;
|
|
180
|
+
this.attrs = {};
|
|
181
|
+
}
|
|
182
|
+
ngOnChanges(changes) {
|
|
183
|
+
if (changes.field || changes.editable || changes.attrs) {
|
|
184
|
+
this.viewContainer.clear();
|
|
185
|
+
if (this.inlineRef) {
|
|
186
|
+
this.inlineRef.remove();
|
|
187
|
+
this.inlineRef = null;
|
|
188
|
+
}
|
|
189
|
+
this.updateView();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
updateView() {
|
|
193
|
+
const field = this.field;
|
|
194
|
+
if (this.editable && field && field.editableFirstPart && field.editableLastPart) {
|
|
195
|
+
this.renderInlineWrapper(field.editableFirstPart, field.editableLastPart);
|
|
196
|
+
}
|
|
197
|
+
else if (field && (field.href || field.value)) {
|
|
198
|
+
const props = field.href ? field : field.value;
|
|
199
|
+
const linkText = field.text || field.value.text || field.href || field.value.href;
|
|
200
|
+
const mergedAttrs = Object.assign(Object.assign({}, props), this.attrs);
|
|
201
|
+
this.renderTemplate(mergedAttrs, linkText);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
renderTemplate(props, linkText) {
|
|
205
|
+
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
206
|
+
viewRef.rootNodes.forEach((node) => {
|
|
207
|
+
Object.entries(props).forEach(([key, propValue]) => {
|
|
208
|
+
if (key === 'href') {
|
|
209
|
+
const isInvalidLink = !propValue || /^https?:\/\/$/.test(propValue);
|
|
210
|
+
if (isInvalidLink) {
|
|
211
|
+
if (!node.href) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
propValue = node.href;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (key === 'class' && node.className) {
|
|
218
|
+
propValue += ` ${node.className}`;
|
|
219
|
+
}
|
|
220
|
+
this.renderer.setAttribute(node, key, propValue);
|
|
221
|
+
});
|
|
222
|
+
if (node.childNodes && node.childNodes.length === 0 && linkText) {
|
|
223
|
+
node.textContent = linkText;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
renderInlineWrapper(editableFirstPart, editableLastPart) {
|
|
228
|
+
const span = this.renderer.createElement('span');
|
|
229
|
+
span.className = 'sc-link-wrapper';
|
|
230
|
+
span.innerHTML = editableFirstPart + editableLastPart;
|
|
231
|
+
// assign attributes from template to inline wrapper
|
|
232
|
+
const attrs = Object.assign(Object.assign({}, this.getElementAttrs()), this.attrs);
|
|
233
|
+
Object.entries(attrs).forEach(([key, attrValue]) => this.renderer.setAttribute(span, key, attrValue));
|
|
234
|
+
this.viewContainer.createEmbeddedView(this.templateRef);
|
|
235
|
+
const parentNode = this.renderer.parentNode(this.elementRef.nativeElement);
|
|
236
|
+
this.renderer.insertBefore(parentNode, span, this.elementRef.nativeElement);
|
|
237
|
+
this.inlineRef = span;
|
|
238
|
+
}
|
|
239
|
+
getElementAttrs() {
|
|
240
|
+
const view = this.templateRef.createEmbeddedView(null);
|
|
241
|
+
const element = view.rootNodes[0];
|
|
242
|
+
if (!element) {
|
|
243
|
+
return {};
|
|
244
|
+
}
|
|
245
|
+
const attrs = {};
|
|
246
|
+
for (let i = 0; i < element.attributes.length; i++) {
|
|
247
|
+
const attr = element.attributes.item(i);
|
|
248
|
+
if (attr) {
|
|
249
|
+
attrs[attr.name] = attr.value;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return attrs;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
LinkDirective.decorators = [
|
|
256
|
+
{ type: Directive, args: [{ selector: '[scLink]' },] }
|
|
257
|
+
];
|
|
258
|
+
LinkDirective.ctorParameters = () => [
|
|
259
|
+
{ type: ViewContainerRef },
|
|
260
|
+
{ type: TemplateRef },
|
|
261
|
+
{ type: Renderer2 },
|
|
262
|
+
{ type: ElementRef }
|
|
263
|
+
];
|
|
264
|
+
LinkDirective.propDecorators = {
|
|
265
|
+
editable: [{ type: Input, args: ['scLinkEditable',] }],
|
|
266
|
+
attrs: [{ type: Input, args: ['scLinkAttrs',] }],
|
|
267
|
+
field: [{ type: Input, args: ['scLink',] }]
|
|
268
268
|
};
|
|
269
269
|
|
|
270
|
-
class RouterLinkDirective extends LinkDirective {
|
|
271
|
-
constructor(viewContainer, templateRef, renderer, elementRef, router) {
|
|
272
|
-
super(viewContainer, templateRef, renderer, elementRef);
|
|
273
|
-
this.router = router;
|
|
274
|
-
this.editable = true;
|
|
275
|
-
this.attrs = {};
|
|
276
|
-
}
|
|
277
|
-
renderTemplate(props, linkText) {
|
|
278
|
-
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
279
|
-
viewRef.rootNodes.forEach((node) => {
|
|
280
|
-
Object.entries(props).forEach(([key, propValue]) => {
|
|
281
|
-
this.renderer.setAttribute(node, key, propValue);
|
|
282
|
-
if (key === 'href') {
|
|
283
|
-
this.renderer.listen(node, 'click', (event) => {
|
|
284
|
-
this.router.navigate([propValue]);
|
|
285
|
-
event.preventDefault();
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
if (node.childNodes && node.childNodes.length === 0 && linkText) {
|
|
290
|
-
node.textContent = linkText;
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
RouterLinkDirective.decorators = [
|
|
296
|
-
{ type: Directive, args: [{ selector: '[scRouterLink]' },] }
|
|
297
|
-
];
|
|
298
|
-
RouterLinkDirective.ctorParameters = () => [
|
|
299
|
-
{ type: ViewContainerRef },
|
|
300
|
-
{ type: TemplateRef },
|
|
301
|
-
{ type: Renderer2 },
|
|
302
|
-
{ type: ElementRef },
|
|
303
|
-
{ type: Router }
|
|
304
|
-
];
|
|
305
|
-
RouterLinkDirective.propDecorators = {
|
|
306
|
-
editable: [{ type: Input, args: ['scRouterLinkEditable',] }],
|
|
307
|
-
attrs: [{ type: Input, args: ['scRouterLinkAttrs',] }],
|
|
308
|
-
field: [{ type: Input, args: ['scRouterLink',] }]
|
|
270
|
+
class RouterLinkDirective extends LinkDirective {
|
|
271
|
+
constructor(viewContainer, templateRef, renderer, elementRef, router) {
|
|
272
|
+
super(viewContainer, templateRef, renderer, elementRef);
|
|
273
|
+
this.router = router;
|
|
274
|
+
this.editable = true;
|
|
275
|
+
this.attrs = {};
|
|
276
|
+
}
|
|
277
|
+
renderTemplate(props, linkText) {
|
|
278
|
+
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
279
|
+
viewRef.rootNodes.forEach((node) => {
|
|
280
|
+
Object.entries(props).forEach(([key, propValue]) => {
|
|
281
|
+
this.renderer.setAttribute(node, key, propValue);
|
|
282
|
+
if (key === 'href') {
|
|
283
|
+
this.renderer.listen(node, 'click', (event) => {
|
|
284
|
+
this.router.navigate([propValue]);
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
if (node.childNodes && node.childNodes.length === 0 && linkText) {
|
|
290
|
+
node.textContent = linkText;
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
RouterLinkDirective.decorators = [
|
|
296
|
+
{ type: Directive, args: [{ selector: '[scRouterLink]' },] }
|
|
297
|
+
];
|
|
298
|
+
RouterLinkDirective.ctorParameters = () => [
|
|
299
|
+
{ type: ViewContainerRef },
|
|
300
|
+
{ type: TemplateRef },
|
|
301
|
+
{ type: Renderer2 },
|
|
302
|
+
{ type: ElementRef },
|
|
303
|
+
{ type: Router }
|
|
304
|
+
];
|
|
305
|
+
RouterLinkDirective.propDecorators = {
|
|
306
|
+
editable: [{ type: Input, args: ['scRouterLinkEditable',] }],
|
|
307
|
+
attrs: [{ type: Input, args: ['scRouterLinkAttrs',] }],
|
|
308
|
+
field: [{ type: Input, args: ['scRouterLink',] }]
|
|
309
309
|
};
|
|
310
310
|
|
|
311
|
-
class GenericLinkDirective extends LinkDirective {
|
|
312
|
-
constructor(viewContainer, templateRef, renderer, elementRef, router) {
|
|
313
|
-
super(viewContainer, templateRef, renderer, elementRef);
|
|
314
|
-
this.router = router;
|
|
315
|
-
this.editable = true;
|
|
316
|
-
this.attrs = {};
|
|
317
|
-
}
|
|
318
|
-
renderTemplate(props, linkText) {
|
|
319
|
-
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
320
|
-
viewRef.rootNodes.forEach((node) => {
|
|
321
|
-
Object.entries(props).forEach(([key, propValue]) => {
|
|
322
|
-
if (key === 'href' && !this.isAbsoluteUrl(propValue)) {
|
|
323
|
-
const urlTree = this.router.createUrlTree([propValue], this.extras);
|
|
324
|
-
this.renderer.setAttribute(node, key, this.router.serializeUrl(urlTree));
|
|
325
|
-
this.renderer.listen(node, 'click', (event) => {
|
|
326
|
-
this.router.navigate([propValue], this.extras);
|
|
327
|
-
event.preventDefault();
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
else {
|
|
331
|
-
this.renderer.setAttribute(node, key, propValue);
|
|
332
|
-
}
|
|
333
|
-
});
|
|
334
|
-
if (node.childNodes && node.childNodes.length === 0 && linkText) {
|
|
335
|
-
node.textContent = linkText;
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
isAbsoluteUrl(url) {
|
|
340
|
-
if (url === null) {
|
|
341
|
-
return false;
|
|
342
|
-
}
|
|
343
|
-
if (typeof url !== 'string') {
|
|
344
|
-
throw new TypeError('Expected a string');
|
|
345
|
-
}
|
|
346
|
-
return /^[a-z][a-z0-9+.-]*:/.test(url);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
GenericLinkDirective.decorators = [
|
|
350
|
-
{ type: Directive, args: [{ selector: '[scGenericLink]' },] }
|
|
351
|
-
];
|
|
352
|
-
GenericLinkDirective.ctorParameters = () => [
|
|
353
|
-
{ type: ViewContainerRef },
|
|
354
|
-
{ type: TemplateRef },
|
|
355
|
-
{ type: Renderer2 },
|
|
356
|
-
{ type: ElementRef },
|
|
357
|
-
{ type: Router }
|
|
358
|
-
];
|
|
359
|
-
GenericLinkDirective.propDecorators = {
|
|
360
|
-
editable: [{ type: Input, args: ['scGenericLinkEditable',] }],
|
|
361
|
-
attrs: [{ type: Input, args: ['scGenericLinkAttrs',] }],
|
|
362
|
-
field: [{ type: Input, args: ['scGenericLink',] }],
|
|
363
|
-
extras: [{ type: Input, args: ['scGenericLinkExtras',] }]
|
|
311
|
+
class GenericLinkDirective extends LinkDirective {
|
|
312
|
+
constructor(viewContainer, templateRef, renderer, elementRef, router) {
|
|
313
|
+
super(viewContainer, templateRef, renderer, elementRef);
|
|
314
|
+
this.router = router;
|
|
315
|
+
this.editable = true;
|
|
316
|
+
this.attrs = {};
|
|
317
|
+
}
|
|
318
|
+
renderTemplate(props, linkText) {
|
|
319
|
+
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
320
|
+
viewRef.rootNodes.forEach((node) => {
|
|
321
|
+
Object.entries(props).forEach(([key, propValue]) => {
|
|
322
|
+
if (key === 'href' && !this.isAbsoluteUrl(propValue)) {
|
|
323
|
+
const urlTree = this.router.createUrlTree([propValue], this.extras);
|
|
324
|
+
this.renderer.setAttribute(node, key, this.router.serializeUrl(urlTree));
|
|
325
|
+
this.renderer.listen(node, 'click', (event) => {
|
|
326
|
+
this.router.navigate([propValue], this.extras);
|
|
327
|
+
event.preventDefault();
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
this.renderer.setAttribute(node, key, propValue);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
if (node.childNodes && node.childNodes.length === 0 && linkText) {
|
|
335
|
+
node.textContent = linkText;
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
isAbsoluteUrl(url) {
|
|
340
|
+
if (url === null) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
if (typeof url !== 'string') {
|
|
344
|
+
throw new TypeError('Expected a string');
|
|
345
|
+
}
|
|
346
|
+
return /^[a-z][a-z0-9+.-]*:/.test(url);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
GenericLinkDirective.decorators = [
|
|
350
|
+
{ type: Directive, args: [{ selector: '[scGenericLink]' },] }
|
|
351
|
+
];
|
|
352
|
+
GenericLinkDirective.ctorParameters = () => [
|
|
353
|
+
{ type: ViewContainerRef },
|
|
354
|
+
{ type: TemplateRef },
|
|
355
|
+
{ type: Renderer2 },
|
|
356
|
+
{ type: ElementRef },
|
|
357
|
+
{ type: Router }
|
|
358
|
+
];
|
|
359
|
+
GenericLinkDirective.propDecorators = {
|
|
360
|
+
editable: [{ type: Input, args: ['scGenericLinkEditable',] }],
|
|
361
|
+
attrs: [{ type: Input, args: ['scGenericLinkAttrs',] }],
|
|
362
|
+
field: [{ type: Input, args: ['scGenericLink',] }],
|
|
363
|
+
extras: [{ type: Input, args: ['scGenericLinkExtras',] }]
|
|
364
364
|
};
|
|
365
365
|
|
|
366
|
-
/** Registers a statically loaded component */
|
|
367
|
-
class ComponentNameAndType {
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* @param {any} object
|
|
371
|
-
*/
|
|
372
|
-
function instanceOfComponentNameAndType(object) {
|
|
373
|
-
return 'type' in object;
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* @param {any} object
|
|
377
|
-
*/
|
|
378
|
-
function instanceOfComponentNameAndModule(object) {
|
|
379
|
-
return 'module' in object;
|
|
380
|
-
}
|
|
381
|
-
const PLACEHOLDER_COMPONENTS = new InjectionToken('Sc.placeholder.components');
|
|
382
|
-
const PLACEHOLDER_LAZY_COMPONENTS = new InjectionToken('Sc.placeholder.lazyComponents');
|
|
383
|
-
const PLACEHOLDER_MISSING_COMPONENT_COMPONENT = new InjectionToken('Sc.placeholder.missingComponentComponent');
|
|
366
|
+
/** Registers a statically loaded component */
|
|
367
|
+
class ComponentNameAndType {
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* @param {any} object
|
|
371
|
+
*/
|
|
372
|
+
function instanceOfComponentNameAndType(object) {
|
|
373
|
+
return 'type' in object;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* @param {any} object
|
|
377
|
+
*/
|
|
378
|
+
function instanceOfComponentNameAndModule(object) {
|
|
379
|
+
return 'module' in object;
|
|
380
|
+
}
|
|
381
|
+
const PLACEHOLDER_COMPONENTS = new InjectionToken('Sc.placeholder.components');
|
|
382
|
+
const PLACEHOLDER_LAZY_COMPONENTS = new InjectionToken('Sc.placeholder.lazyComponents');
|
|
383
|
+
const PLACEHOLDER_MISSING_COMPONENT_COMPONENT = new InjectionToken('Sc.placeholder.missingComponentComponent');
|
|
384
384
|
const DYNAMIC_COMPONENT = new InjectionToken('Sc.placeholder.dynamicComponent');
|
|
385
385
|
|
|
386
|
-
class RawComponent {
|
|
387
|
-
constructor(renderer, elementRef) {
|
|
388
|
-
this.renderer = renderer;
|
|
389
|
-
this.elementRef = elementRef;
|
|
390
|
-
}
|
|
391
|
-
ngOnInit() {
|
|
392
|
-
const el = this.renderer.createElement(this.rendering.name);
|
|
393
|
-
const contents = this.renderer.createText(this.rendering.contents || '');
|
|
394
|
-
const attributes = this.rendering.attributes;
|
|
395
|
-
for (const attr in attributes) {
|
|
396
|
-
// eslint-disable-next-line no-prototype-builtins
|
|
397
|
-
if (attributes.hasOwnProperty(attr)) {
|
|
398
|
-
const value = attributes[attr];
|
|
399
|
-
this.renderer.setAttribute(el, attr, value || '');
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
this.renderer.appendChild(el, contents);
|
|
403
|
-
const parentNode = this.renderer.parentNode(this.elementRef.nativeElement);
|
|
404
|
-
this.renderer.insertBefore(parentNode, el, this.elementRef.nativeElement);
|
|
405
|
-
parentNode.removeChild(this.elementRef.nativeElement);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
RawComponent.decorators = [
|
|
409
|
-
{ type: Component, args: [{
|
|
410
|
-
selector: 'sc-raw',
|
|
411
|
-
template: ''
|
|
412
|
-
},] }
|
|
413
|
-
];
|
|
414
|
-
RawComponent.ctorParameters = () => [
|
|
415
|
-
{ type: Renderer2 },
|
|
416
|
-
{ type: ElementRef }
|
|
417
|
-
];
|
|
418
|
-
RawComponent.propDecorators = {
|
|
419
|
-
rendering: [{ type: Input }]
|
|
386
|
+
class RawComponent {
|
|
387
|
+
constructor(renderer, elementRef) {
|
|
388
|
+
this.renderer = renderer;
|
|
389
|
+
this.elementRef = elementRef;
|
|
390
|
+
}
|
|
391
|
+
ngOnInit() {
|
|
392
|
+
const el = this.renderer.createElement(this.rendering.name);
|
|
393
|
+
const contents = this.renderer.createText(this.rendering.contents || '');
|
|
394
|
+
const attributes = this.rendering.attributes;
|
|
395
|
+
for (const attr in attributes) {
|
|
396
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
397
|
+
if (attributes.hasOwnProperty(attr)) {
|
|
398
|
+
const value = attributes[attr];
|
|
399
|
+
this.renderer.setAttribute(el, attr, value || '');
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
this.renderer.appendChild(el, contents);
|
|
403
|
+
const parentNode = this.renderer.parentNode(this.elementRef.nativeElement);
|
|
404
|
+
this.renderer.insertBefore(parentNode, el, this.elementRef.nativeElement);
|
|
405
|
+
parentNode.removeChild(this.elementRef.nativeElement);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
RawComponent.decorators = [
|
|
409
|
+
{ type: Component, args: [{
|
|
410
|
+
selector: 'sc-raw',
|
|
411
|
+
template: ''
|
|
412
|
+
},] }
|
|
413
|
+
];
|
|
414
|
+
RawComponent.ctorParameters = () => [
|
|
415
|
+
{ type: Renderer2 },
|
|
416
|
+
{ type: ElementRef }
|
|
417
|
+
];
|
|
418
|
+
RawComponent.propDecorators = {
|
|
419
|
+
rendering: [{ type: Input }]
|
|
420
420
|
};
|
|
421
421
|
|
|
422
|
-
/**
|
|
423
|
-
* @param {HtmlElementRendering | ComponentRendering} rendering
|
|
424
|
-
*/
|
|
425
|
-
function isRawRendering(rendering) {
|
|
426
|
-
return (!rendering.componentName &&
|
|
427
|
-
rendering.name !== undefined);
|
|
422
|
+
/**
|
|
423
|
+
* @param {HtmlElementRendering | ComponentRendering} rendering
|
|
424
|
+
*/
|
|
425
|
+
function isRawRendering(rendering) {
|
|
426
|
+
return (!rendering.componentName &&
|
|
427
|
+
rendering.name !== undefined);
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
-
class JssComponentFactoryService {
|
|
431
|
-
constructor(injector, compiler, components, lazyComponents) {
|
|
432
|
-
this.injector = injector;
|
|
433
|
-
this.compiler = compiler;
|
|
434
|
-
this.components = components;
|
|
435
|
-
this.lazyComponents = lazyComponents;
|
|
436
|
-
this.componentMap = new Map();
|
|
437
|
-
this.lazyComponentMap = new Map();
|
|
438
|
-
this.components.forEach((c) => this.componentMap.set(c.name, c.type));
|
|
439
|
-
if (this.lazyComponents) {
|
|
440
|
-
this.lazyComponents.forEach((c) => this.lazyComponentMap.set(c.path, c));
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
loadModuleFactory(lazyComponent) {
|
|
444
|
-
return lazyComponent.loadChildren().then((loaded) => {
|
|
445
|
-
if (loaded instanceof NgModuleFactory) {
|
|
446
|
-
return loaded;
|
|
447
|
-
}
|
|
448
|
-
else {
|
|
449
|
-
return this.compiler.compileModuleAsync(loaded);
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
getComponent(component) {
|
|
454
|
-
const loadedComponent = this.componentMap.get(component.componentName);
|
|
455
|
-
if (loadedComponent) {
|
|
456
|
-
return Promise.resolve({
|
|
457
|
-
componentDefinition: component,
|
|
458
|
-
componentImplementation: this.componentMap.get(component.componentName),
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
const lazyComponent = this.lazyComponentMap.get(component.componentName);
|
|
462
|
-
if (lazyComponent) {
|
|
463
|
-
return this.loadModuleFactory(lazyComponent).then((ngModuleFactory) => {
|
|
464
|
-
let componentType = null;
|
|
465
|
-
const moduleRef = ngModuleFactory.create(this.injector);
|
|
466
|
-
const dynamicComponentType = moduleRef.injector.get(DYNAMIC_COMPONENT);
|
|
467
|
-
if (!dynamicComponentType) {
|
|
468
|
-
throw new Error(`JssComponentFactoryService: Lazy load module for component "${lazyComponent.path}" missing DYNAMIC_COMPONENT provider. Missing JssModule.forChild()?`);
|
|
469
|
-
}
|
|
470
|
-
if (component.componentName in dynamicComponentType) {
|
|
471
|
-
componentType = dynamicComponentType[component.componentName];
|
|
472
|
-
}
|
|
473
|
-
else {
|
|
474
|
-
if (typeof dynamicComponentType === 'function') {
|
|
475
|
-
componentType = dynamicComponentType;
|
|
476
|
-
}
|
|
477
|
-
else {
|
|
478
|
-
throw new Error(`JssComponentFactoryService: Lazy load module for component "${lazyComponent.path}" missing DYNAMIC_COMPONENT provider. Missing JssModule.forChild()?`);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
return {
|
|
482
|
-
componentDefinition: component,
|
|
483
|
-
componentImplementation: componentType,
|
|
484
|
-
componentFactory: moduleRef.componentFactoryResolver.resolveComponentFactory(componentType),
|
|
485
|
-
};
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
return Promise.resolve({
|
|
489
|
-
componentDefinition: component,
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
getComponents(components) {
|
|
493
|
-
// acquire all components and keep them in order while handling their potential async-ness
|
|
494
|
-
return Promise.all(components.map((component) => isRawRendering(component) ? this.getRawComponent(component) : this.getComponent(component)));
|
|
495
|
-
}
|
|
496
|
-
getRawComponent(component) {
|
|
497
|
-
return Promise.resolve({
|
|
498
|
-
componentImplementation: RawComponent,
|
|
499
|
-
componentDefinition: component,
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
JssComponentFactoryService.decorators = [
|
|
504
|
-
{ type: Injectable }
|
|
505
|
-
];
|
|
506
|
-
JssComponentFactoryService.ctorParameters = () => [
|
|
507
|
-
{ type: Injector },
|
|
508
|
-
{ type: Compiler },
|
|
509
|
-
{ type: Array, decorators: [{ type: Inject, args: [PLACEHOLDER_COMPONENTS,] }] },
|
|
510
|
-
{ type: Array, decorators: [{ type: Inject, args: [PLACEHOLDER_LAZY_COMPONENTS,] }] }
|
|
430
|
+
class JssComponentFactoryService {
|
|
431
|
+
constructor(injector, compiler, components, lazyComponents) {
|
|
432
|
+
this.injector = injector;
|
|
433
|
+
this.compiler = compiler;
|
|
434
|
+
this.components = components;
|
|
435
|
+
this.lazyComponents = lazyComponents;
|
|
436
|
+
this.componentMap = new Map();
|
|
437
|
+
this.lazyComponentMap = new Map();
|
|
438
|
+
this.components.forEach((c) => this.componentMap.set(c.name, c.type));
|
|
439
|
+
if (this.lazyComponents) {
|
|
440
|
+
this.lazyComponents.forEach((c) => this.lazyComponentMap.set(c.path, c));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
loadModuleFactory(lazyComponent) {
|
|
444
|
+
return lazyComponent.loadChildren().then((loaded) => {
|
|
445
|
+
if (loaded instanceof NgModuleFactory) {
|
|
446
|
+
return loaded;
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
return this.compiler.compileModuleAsync(loaded);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
getComponent(component) {
|
|
454
|
+
const loadedComponent = this.componentMap.get(component.componentName);
|
|
455
|
+
if (loadedComponent) {
|
|
456
|
+
return Promise.resolve({
|
|
457
|
+
componentDefinition: component,
|
|
458
|
+
componentImplementation: this.componentMap.get(component.componentName),
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
const lazyComponent = this.lazyComponentMap.get(component.componentName);
|
|
462
|
+
if (lazyComponent) {
|
|
463
|
+
return this.loadModuleFactory(lazyComponent).then((ngModuleFactory) => {
|
|
464
|
+
let componentType = null;
|
|
465
|
+
const moduleRef = ngModuleFactory.create(this.injector);
|
|
466
|
+
const dynamicComponentType = moduleRef.injector.get(DYNAMIC_COMPONENT);
|
|
467
|
+
if (!dynamicComponentType) {
|
|
468
|
+
throw new Error(`JssComponentFactoryService: Lazy load module for component "${lazyComponent.path}" missing DYNAMIC_COMPONENT provider. Missing JssModule.forChild()?`);
|
|
469
|
+
}
|
|
470
|
+
if (component.componentName in dynamicComponentType) {
|
|
471
|
+
componentType = dynamicComponentType[component.componentName];
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
if (typeof dynamicComponentType === 'function') {
|
|
475
|
+
componentType = dynamicComponentType;
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
throw new Error(`JssComponentFactoryService: Lazy load module for component "${lazyComponent.path}" missing DYNAMIC_COMPONENT provider. Missing JssModule.forChild()?`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
componentDefinition: component,
|
|
483
|
+
componentImplementation: componentType,
|
|
484
|
+
componentFactory: moduleRef.componentFactoryResolver.resolveComponentFactory(componentType),
|
|
485
|
+
};
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
return Promise.resolve({
|
|
489
|
+
componentDefinition: component,
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
getComponents(components) {
|
|
493
|
+
// acquire all components and keep them in order while handling their potential async-ness
|
|
494
|
+
return Promise.all(components.map((component) => isRawRendering(component) ? this.getRawComponent(component) : this.getComponent(component)));
|
|
495
|
+
}
|
|
496
|
+
getRawComponent(component) {
|
|
497
|
+
return Promise.resolve({
|
|
498
|
+
componentImplementation: RawComponent,
|
|
499
|
+
componentDefinition: component,
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
JssComponentFactoryService.decorators = [
|
|
504
|
+
{ type: Injectable }
|
|
505
|
+
];
|
|
506
|
+
JssComponentFactoryService.ctorParameters = () => [
|
|
507
|
+
{ type: Injector },
|
|
508
|
+
{ type: Compiler },
|
|
509
|
+
{ type: Array, decorators: [{ type: Inject, args: [PLACEHOLDER_COMPONENTS,] }] },
|
|
510
|
+
{ type: Array, decorators: [{ type: Inject, args: [PLACEHOLDER_LAZY_COMPONENTS,] }] }
|
|
511
511
|
];
|
|
512
512
|
|
|
513
|
-
class PlaceholderLoadingDirective {
|
|
514
|
-
constructor(templateRef) {
|
|
515
|
-
this.templateRef = templateRef;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
PlaceholderLoadingDirective.decorators = [
|
|
519
|
-
{ type: Directive, args: [{
|
|
520
|
-
selector: '[scPlaceholderLoading]',
|
|
521
|
-
},] }
|
|
522
|
-
];
|
|
523
|
-
PlaceholderLoadingDirective.ctorParameters = () => [
|
|
524
|
-
{ type: TemplateRef }
|
|
513
|
+
class PlaceholderLoadingDirective {
|
|
514
|
+
constructor(templateRef) {
|
|
515
|
+
this.templateRef = templateRef;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
PlaceholderLoadingDirective.decorators = [
|
|
519
|
+
{ type: Directive, args: [{
|
|
520
|
+
selector: '[scPlaceholderLoading]',
|
|
521
|
+
},] }
|
|
522
|
+
];
|
|
523
|
+
PlaceholderLoadingDirective.ctorParameters = () => [
|
|
524
|
+
{ type: TemplateRef }
|
|
525
525
|
];
|
|
526
526
|
|
|
527
|
-
class RenderEachDirective {
|
|
528
|
-
constructor(templateRef) {
|
|
529
|
-
this.templateRef = templateRef;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
RenderEachDirective.decorators = [
|
|
533
|
-
{ type: Directive, args: [{
|
|
534
|
-
selector: '[renderEach]',
|
|
535
|
-
},] }
|
|
536
|
-
];
|
|
537
|
-
RenderEachDirective.ctorParameters = () => [
|
|
538
|
-
{ type: TemplateRef }
|
|
527
|
+
class RenderEachDirective {
|
|
528
|
+
constructor(templateRef) {
|
|
529
|
+
this.templateRef = templateRef;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
RenderEachDirective.decorators = [
|
|
533
|
+
{ type: Directive, args: [{
|
|
534
|
+
selector: '[renderEach]',
|
|
535
|
+
},] }
|
|
536
|
+
];
|
|
537
|
+
RenderEachDirective.ctorParameters = () => [
|
|
538
|
+
{ type: TemplateRef }
|
|
539
539
|
];
|
|
540
540
|
|
|
541
|
-
class RenderEmptyDirective {
|
|
542
|
-
constructor(templateRef) {
|
|
543
|
-
this.templateRef = templateRef;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
RenderEmptyDirective.decorators = [
|
|
547
|
-
{ type: Directive, args: [{
|
|
548
|
-
selector: '[renderEmpty]',
|
|
549
|
-
},] }
|
|
550
|
-
];
|
|
551
|
-
RenderEmptyDirective.ctorParameters = () => [
|
|
552
|
-
{ type: TemplateRef }
|
|
541
|
+
class RenderEmptyDirective {
|
|
542
|
+
constructor(templateRef) {
|
|
543
|
+
this.templateRef = templateRef;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
RenderEmptyDirective.decorators = [
|
|
547
|
+
{ type: Directive, args: [{
|
|
548
|
+
selector: '[renderEmpty]',
|
|
549
|
+
},] }
|
|
550
|
+
];
|
|
551
|
+
RenderEmptyDirective.ctorParameters = () => [
|
|
552
|
+
{ type: TemplateRef }
|
|
553
553
|
];
|
|
554
554
|
|
|
555
|
-
/* eslint-disable @angular-eslint/no-conflicting-lifecycle */
|
|
556
|
-
/**
|
|
557
|
-
* @param {ComponentRendering} rendering
|
|
558
|
-
* @param {string} name
|
|
559
|
-
*/
|
|
560
|
-
function getPlaceholder(rendering, name) {
|
|
561
|
-
if (rendering && rendering.placeholders && Object.keys(rendering.placeholders).length > 0) {
|
|
562
|
-
return rendering.placeholders[name];
|
|
563
|
-
}
|
|
564
|
-
return null;
|
|
565
|
-
}
|
|
566
|
-
class PlaceholderComponent {
|
|
567
|
-
constructor(componentFactoryResolver, differs, componentFactory, changeDetectorRef, elementRef, renderer, missingComponentComponent) {
|
|
568
|
-
this.componentFactoryResolver = componentFactoryResolver;
|
|
569
|
-
this.differs = differs;
|
|
570
|
-
this.componentFactory = componentFactory;
|
|
571
|
-
this.changeDetectorRef = changeDetectorRef;
|
|
572
|
-
this.elementRef = elementRef;
|
|
573
|
-
this.renderer = renderer;
|
|
574
|
-
this.missingComponentComponent = missingComponentComponent;
|
|
575
|
-
this._componentInstances = [];
|
|
576
|
-
this.destroyed = false;
|
|
577
|
-
this.parentStyleAttribute = '';
|
|
578
|
-
this.isLoading = true;
|
|
579
|
-
this.loaded = new EventEmitter();
|
|
580
|
-
}
|
|
581
|
-
set inputs(value) {
|
|
582
|
-
this._inputs = value;
|
|
583
|
-
if (!this._differ && value) {
|
|
584
|
-
this._differ = this.differs.find(value).create();
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
ngOnInit() {
|
|
588
|
-
// just to ensure the element exists
|
|
589
|
-
const elem = this.elementRef.nativeElement;
|
|
590
|
-
if (elem) {
|
|
591
|
-
const attributes = elem.attributes;
|
|
592
|
-
for (let i = 0; i < attributes.length; i++) {
|
|
593
|
-
const attr = attributes.item(i);
|
|
594
|
-
if (attr && attr.name.indexOf('_ngcontent') !== -1) {
|
|
595
|
-
this.parentStyleAttribute = attr.name;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
ngOnDestroy() {
|
|
601
|
-
this.destroyed = true;
|
|
602
|
-
this._componentInstances = [];
|
|
603
|
-
}
|
|
604
|
-
ngOnChanges(changes) {
|
|
605
|
-
if (changes.rendering || changes.renderings) {
|
|
606
|
-
this._render();
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
ngDoCheck() {
|
|
610
|
-
if (!this._differ || !this._inputs || this._componentInstances.length === 0) {
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
const changes = this._differ.diff(this._inputs);
|
|
614
|
-
if (!changes) {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
const updates = {};
|
|
618
|
-
changes.forEachRemovedItem((change) => (updates[change.key] = null));
|
|
619
|
-
changes.forEachAddedItem((change) => (updates[change.key] = change.currentValue));
|
|
620
|
-
changes.forEachChangedItem((change) => (updates[change.key] = change.currentValue));
|
|
621
|
-
this._componentInstances.forEach((componentInstance) => this._setComponentInputs(componentInstance, updates));
|
|
622
|
-
}
|
|
623
|
-
_setComponentInputs(componentInstance, inputs) {
|
|
624
|
-
Object.entries(inputs).forEach(([input, inputValue]) => (componentInstance[input] = inputValue));
|
|
625
|
-
}
|
|
626
|
-
_subscribeComponentOutputs(componentInstance, outputs) {
|
|
627
|
-
Object.keys(outputs)
|
|
628
|
-
.filter((output) => componentInstance[output] && componentInstance[output] instanceof Observable)
|
|
629
|
-
.forEach((output) => componentInstance[output]
|
|
630
|
-
.pipe(takeWhile(() => !this.destroyed))
|
|
631
|
-
.subscribe(outputs[output]));
|
|
632
|
-
}
|
|
633
|
-
_render() {
|
|
634
|
-
this._componentInstances = [];
|
|
635
|
-
this.view.clear();
|
|
636
|
-
if (!this.rendering && !this.renderings) {
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
if (!this.name && !this.renderings) {
|
|
640
|
-
console.warn('Placeholder name was not specified, and explicit renderings array was not passed. Placeholder requires either name and rendering, or renderings.');
|
|
641
|
-
this.isLoading = false;
|
|
642
|
-
return;
|
|
643
|
-
}
|
|
644
|
-
const placeholder = this.renderings || getPlaceholder(this.rendering, this.name || '');
|
|
645
|
-
if (!placeholder) {
|
|
646
|
-
console.warn(`Placeholder '${this.name}' was not found in the current rendering data`, JSON.stringify(this.rendering, null, 2));
|
|
647
|
-
this.isLoading = false;
|
|
648
|
-
return;
|
|
649
|
-
}
|
|
650
|
-
// if the placeholder is empty (contains only raw renderings), then we may need to use the empty template if it's defined
|
|
651
|
-
const placeholderIsEmpty = placeholder.every((rendering) => isRawRendering(rendering));
|
|
652
|
-
if (this.renderEmptyTemplate && placeholderIsEmpty) {
|
|
653
|
-
this.view.createEmbeddedView(this.renderEmptyTemplate.templateRef, {
|
|
654
|
-
renderings: placeholder,
|
|
655
|
-
});
|
|
656
|
-
this.isLoading = false;
|
|
657
|
-
}
|
|
658
|
-
else {
|
|
659
|
-
this.componentFactory
|
|
660
|
-
.getComponents(placeholder)
|
|
661
|
-
.then((components) => components.forEach((rendering, index) => {
|
|
662
|
-
if (this.renderEachTemplate && !isRawRendering(rendering.componentDefinition)) {
|
|
663
|
-
this._renderTemplatedComponent(rendering.componentDefinition, index);
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
this._renderEmbeddedComponent(rendering, index);
|
|
667
|
-
}
|
|
668
|
-
this.isLoading = false;
|
|
669
|
-
}))
|
|
670
|
-
.then(() => {
|
|
671
|
-
this.changeDetectorRef.markForCheck();
|
|
672
|
-
this.loaded.emit(this.name);
|
|
673
|
-
});
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
_renderTemplatedComponent(rendering, index) {
|
|
677
|
-
// the render-each template takes care of all component mapping etc
|
|
678
|
-
// generally using <sc-render-component> which is about like _renderEmbeddedComponent()
|
|
679
|
-
// as a separate component
|
|
680
|
-
this.view.createEmbeddedView(this.renderEachTemplate.templateRef, {
|
|
681
|
-
rendering,
|
|
682
|
-
index,
|
|
683
|
-
});
|
|
684
|
-
}
|
|
685
|
-
_renderEmbeddedComponent(rendering, index) {
|
|
686
|
-
if (!rendering.componentImplementation) {
|
|
687
|
-
const componentName = rendering.componentDefinition.componentName;
|
|
555
|
+
/* eslint-disable @angular-eslint/no-conflicting-lifecycle */
|
|
556
|
+
/**
|
|
557
|
+
* @param {ComponentRendering} rendering
|
|
558
|
+
* @param {string} name
|
|
559
|
+
*/
|
|
560
|
+
function getPlaceholder(rendering, name) {
|
|
561
|
+
if (rendering && rendering.placeholders && Object.keys(rendering.placeholders).length > 0) {
|
|
562
|
+
return rendering.placeholders[name];
|
|
563
|
+
}
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
class PlaceholderComponent {
|
|
567
|
+
constructor(componentFactoryResolver, differs, componentFactory, changeDetectorRef, elementRef, renderer, missingComponentComponent) {
|
|
568
|
+
this.componentFactoryResolver = componentFactoryResolver;
|
|
569
|
+
this.differs = differs;
|
|
570
|
+
this.componentFactory = componentFactory;
|
|
571
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
572
|
+
this.elementRef = elementRef;
|
|
573
|
+
this.renderer = renderer;
|
|
574
|
+
this.missingComponentComponent = missingComponentComponent;
|
|
575
|
+
this._componentInstances = [];
|
|
576
|
+
this.destroyed = false;
|
|
577
|
+
this.parentStyleAttribute = '';
|
|
578
|
+
this.isLoading = true;
|
|
579
|
+
this.loaded = new EventEmitter();
|
|
580
|
+
}
|
|
581
|
+
set inputs(value) {
|
|
582
|
+
this._inputs = value;
|
|
583
|
+
if (!this._differ && value) {
|
|
584
|
+
this._differ = this.differs.find(value).create();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
ngOnInit() {
|
|
588
|
+
// just to ensure the element exists
|
|
589
|
+
const elem = this.elementRef.nativeElement;
|
|
590
|
+
if (elem) {
|
|
591
|
+
const attributes = elem.attributes;
|
|
592
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
593
|
+
const attr = attributes.item(i);
|
|
594
|
+
if (attr && attr.name.indexOf('_ngcontent') !== -1) {
|
|
595
|
+
this.parentStyleAttribute = attr.name;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
ngOnDestroy() {
|
|
601
|
+
this.destroyed = true;
|
|
602
|
+
this._componentInstances = [];
|
|
603
|
+
}
|
|
604
|
+
ngOnChanges(changes) {
|
|
605
|
+
if (changes.rendering || changes.renderings) {
|
|
606
|
+
this._render();
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
ngDoCheck() {
|
|
610
|
+
if (!this._differ || !this._inputs || this._componentInstances.length === 0) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const changes = this._differ.diff(this._inputs);
|
|
614
|
+
if (!changes) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
const updates = {};
|
|
618
|
+
changes.forEachRemovedItem((change) => (updates[change.key] = null));
|
|
619
|
+
changes.forEachAddedItem((change) => (updates[change.key] = change.currentValue));
|
|
620
|
+
changes.forEachChangedItem((change) => (updates[change.key] = change.currentValue));
|
|
621
|
+
this._componentInstances.forEach((componentInstance) => this._setComponentInputs(componentInstance, updates));
|
|
622
|
+
}
|
|
623
|
+
_setComponentInputs(componentInstance, inputs) {
|
|
624
|
+
Object.entries(inputs).forEach(([input, inputValue]) => (componentInstance[input] = inputValue));
|
|
625
|
+
}
|
|
626
|
+
_subscribeComponentOutputs(componentInstance, outputs) {
|
|
627
|
+
Object.keys(outputs)
|
|
628
|
+
.filter((output) => componentInstance[output] && componentInstance[output] instanceof Observable)
|
|
629
|
+
.forEach((output) => componentInstance[output]
|
|
630
|
+
.pipe(takeWhile(() => !this.destroyed))
|
|
631
|
+
.subscribe(outputs[output]));
|
|
632
|
+
}
|
|
633
|
+
_render() {
|
|
634
|
+
this._componentInstances = [];
|
|
635
|
+
this.view.clear();
|
|
636
|
+
if (!this.rendering && !this.renderings) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
if (!this.name && !this.renderings) {
|
|
640
|
+
console.warn('Placeholder name was not specified, and explicit renderings array was not passed. Placeholder requires either name and rendering, or renderings.');
|
|
641
|
+
this.isLoading = false;
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
const placeholder = this.renderings || getPlaceholder(this.rendering, this.name || '');
|
|
645
|
+
if (!placeholder) {
|
|
646
|
+
console.warn(`Placeholder '${this.name}' was not found in the current rendering data`, JSON.stringify(this.rendering, null, 2));
|
|
647
|
+
this.isLoading = false;
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
// if the placeholder is empty (contains only raw renderings), then we may need to use the empty template if it's defined
|
|
651
|
+
const placeholderIsEmpty = placeholder.every((rendering) => isRawRendering(rendering));
|
|
652
|
+
if (this.renderEmptyTemplate && placeholderIsEmpty) {
|
|
653
|
+
this.view.createEmbeddedView(this.renderEmptyTemplate.templateRef, {
|
|
654
|
+
renderings: placeholder,
|
|
655
|
+
});
|
|
656
|
+
this.isLoading = false;
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
this.componentFactory
|
|
660
|
+
.getComponents(placeholder)
|
|
661
|
+
.then((components) => components.forEach((rendering, index) => {
|
|
662
|
+
if (this.renderEachTemplate && !isRawRendering(rendering.componentDefinition)) {
|
|
663
|
+
this._renderTemplatedComponent(rendering.componentDefinition, index);
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
this._renderEmbeddedComponent(rendering, index);
|
|
667
|
+
}
|
|
668
|
+
this.isLoading = false;
|
|
669
|
+
}))
|
|
670
|
+
.then(() => {
|
|
671
|
+
this.changeDetectorRef.markForCheck();
|
|
672
|
+
this.loaded.emit(this.name);
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
_renderTemplatedComponent(rendering, index) {
|
|
677
|
+
// the render-each template takes care of all component mapping etc
|
|
678
|
+
// generally using <sc-render-component> which is about like _renderEmbeddedComponent()
|
|
679
|
+
// as a separate component
|
|
680
|
+
this.view.createEmbeddedView(this.renderEachTemplate.templateRef, {
|
|
681
|
+
rendering,
|
|
682
|
+
index,
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
_renderEmbeddedComponent(rendering, index) {
|
|
686
|
+
if (!rendering.componentImplementation) {
|
|
687
|
+
const componentName = rendering.componentDefinition.componentName;
|
|
688
688
|
console.error(`Placeholder ${this.name} contains unknown component ${componentName}.`, `Ensure component is mapped, like:
|
|
689
689
|
JssModule.withComponents([
|
|
690
690
|
{ name: '${componentName}', type: ${componentName}Component }
|
|
691
|
-
])`);
|
|
692
|
-
rendering.componentImplementation = this.missingComponentComponent;
|
|
693
|
-
}
|
|
694
|
-
const componentFactory = rendering.componentFactory ||
|
|
695
|
-
this.componentFactoryResolver.resolveComponentFactory(rendering.componentImplementation);
|
|
696
|
-
// apply the parent style attribute _ngcontent
|
|
697
|
-
// work-around for https://github.com/angular/angular/issues/12215
|
|
698
|
-
const createdComponentRef = this.view.createComponent(componentFactory, index);
|
|
699
|
-
if (this.parentStyleAttribute) {
|
|
700
|
-
this.renderer.setAttribute(createdComponentRef.location.nativeElement, this.parentStyleAttribute, '');
|
|
701
|
-
}
|
|
702
|
-
const componentInstance = createdComponentRef.instance;
|
|
703
|
-
componentInstance.rendering = rendering.componentDefinition;
|
|
704
|
-
if (this._inputs) {
|
|
705
|
-
this._setComponentInputs(componentInstance, this._inputs);
|
|
706
|
-
}
|
|
707
|
-
if (this.outputs) {
|
|
708
|
-
this._subscribeComponentOutputs(componentInstance, this.outputs);
|
|
709
|
-
}
|
|
710
|
-
this._componentInstances.push(componentInstance);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
PlaceholderComponent.decorators = [
|
|
714
|
-
{ type: Component, args: [{
|
|
715
|
-
selector: 'sc-placeholder,[sc-placeholder]',
|
|
691
|
+
])`);
|
|
692
|
+
rendering.componentImplementation = this.missingComponentComponent;
|
|
693
|
+
}
|
|
694
|
+
const componentFactory = rendering.componentFactory ||
|
|
695
|
+
this.componentFactoryResolver.resolveComponentFactory(rendering.componentImplementation);
|
|
696
|
+
// apply the parent style attribute _ngcontent
|
|
697
|
+
// work-around for https://github.com/angular/angular/issues/12215
|
|
698
|
+
const createdComponentRef = this.view.createComponent(componentFactory, index);
|
|
699
|
+
if (this.parentStyleAttribute) {
|
|
700
|
+
this.renderer.setAttribute(createdComponentRef.location.nativeElement, this.parentStyleAttribute, '');
|
|
701
|
+
}
|
|
702
|
+
const componentInstance = createdComponentRef.instance;
|
|
703
|
+
componentInstance.rendering = rendering.componentDefinition;
|
|
704
|
+
if (this._inputs) {
|
|
705
|
+
this._setComponentInputs(componentInstance, this._inputs);
|
|
706
|
+
}
|
|
707
|
+
if (this.outputs) {
|
|
708
|
+
this._subscribeComponentOutputs(componentInstance, this.outputs);
|
|
709
|
+
}
|
|
710
|
+
this._componentInstances.push(componentInstance);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
PlaceholderComponent.decorators = [
|
|
714
|
+
{ type: Component, args: [{
|
|
715
|
+
selector: 'sc-placeholder,[sc-placeholder]',
|
|
716
716
|
template: `
|
|
717
717
|
<ng-template
|
|
718
718
|
*ngIf="isLoading"
|
|
719
719
|
[ngTemplateOutlet]="placeholderLoading?.templateRef"
|
|
720
720
|
></ng-template>
|
|
721
721
|
<ng-template #view></ng-template>
|
|
722
|
-
`
|
|
723
|
-
},] }
|
|
724
|
-
];
|
|
725
|
-
PlaceholderComponent.ctorParameters = () => [
|
|
726
|
-
{ type: ComponentFactoryResolver },
|
|
727
|
-
{ type: KeyValueDiffers },
|
|
728
|
-
{ type: JssComponentFactoryService },
|
|
729
|
-
{ type: ChangeDetectorRef },
|
|
730
|
-
{ type: ElementRef },
|
|
731
|
-
{ type: Renderer2 },
|
|
732
|
-
{ type: Type, decorators: [{ type: Inject, args: [PLACEHOLDER_MISSING_COMPONENT_COMPONENT,] }] }
|
|
733
|
-
];
|
|
734
|
-
PlaceholderComponent.propDecorators = {
|
|
735
|
-
name: [{ type: Input }],
|
|
736
|
-
rendering: [{ type: Input }],
|
|
737
|
-
renderings: [{ type: Input }],
|
|
738
|
-
outputs: [{ type: Input }],
|
|
739
|
-
loaded: [{ type: Output }],
|
|
740
|
-
view: [{ type: ViewChild, args: ['view', { read: ViewContainerRef, static: true },] }],
|
|
741
|
-
renderEachTemplate: [{ type: ContentChild, args: [RenderEachDirective, { static: true },] }],
|
|
742
|
-
renderEmptyTemplate: [{ type: ContentChild, args: [RenderEmptyDirective, { static: true },] }],
|
|
743
|
-
placeholderLoading: [{ type: ContentChild, args: [PlaceholderLoadingDirective, { static: true },] }],
|
|
744
|
-
inputs: [{ type: Input }]
|
|
722
|
+
`
|
|
723
|
+
},] }
|
|
724
|
+
];
|
|
725
|
+
PlaceholderComponent.ctorParameters = () => [
|
|
726
|
+
{ type: ComponentFactoryResolver },
|
|
727
|
+
{ type: KeyValueDiffers },
|
|
728
|
+
{ type: JssComponentFactoryService },
|
|
729
|
+
{ type: ChangeDetectorRef },
|
|
730
|
+
{ type: ElementRef },
|
|
731
|
+
{ type: Renderer2 },
|
|
732
|
+
{ type: Type, decorators: [{ type: Inject, args: [PLACEHOLDER_MISSING_COMPONENT_COMPONENT,] }] }
|
|
733
|
+
];
|
|
734
|
+
PlaceholderComponent.propDecorators = {
|
|
735
|
+
name: [{ type: Input }],
|
|
736
|
+
rendering: [{ type: Input }],
|
|
737
|
+
renderings: [{ type: Input }],
|
|
738
|
+
outputs: [{ type: Input }],
|
|
739
|
+
loaded: [{ type: Output }],
|
|
740
|
+
view: [{ type: ViewChild, args: ['view', { read: ViewContainerRef, static: true },] }],
|
|
741
|
+
renderEachTemplate: [{ type: ContentChild, args: [RenderEachDirective, { static: true },] }],
|
|
742
|
+
renderEmptyTemplate: [{ type: ContentChild, args: [RenderEmptyDirective, { static: true },] }],
|
|
743
|
+
placeholderLoading: [{ type: ContentChild, args: [PlaceholderLoadingDirective, { static: true },] }],
|
|
744
|
+
inputs: [{ type: Input }]
|
|
745
745
|
};
|
|
746
746
|
|
|
747
|
-
class RichTextDirective {
|
|
748
|
-
constructor(viewContainer, templateRef) {
|
|
749
|
-
this.viewContainer = viewContainer;
|
|
750
|
-
this.templateRef = templateRef;
|
|
751
|
-
this.editable = true;
|
|
752
|
-
}
|
|
753
|
-
ngOnChanges(changes) {
|
|
754
|
-
if (changes.field || changes.editable) {
|
|
755
|
-
if (!this.viewRef) {
|
|
756
|
-
this.viewContainer.clear();
|
|
757
|
-
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
758
|
-
}
|
|
759
|
-
this.updateView();
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
updateView() {
|
|
763
|
-
const field = this.field;
|
|
764
|
-
if (!field || (!field.editable && !field.value)) {
|
|
765
|
-
return;
|
|
766
|
-
}
|
|
767
|
-
const html = field.editable && this.editable ? field.editable : field.value;
|
|
768
|
-
this.viewRef.rootNodes.forEach((node) => {
|
|
769
|
-
node.innerHTML = html;
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
RichTextDirective.decorators = [
|
|
774
|
-
{ type: Directive, args: [{
|
|
775
|
-
selector: '[scRichText]',
|
|
776
|
-
},] }
|
|
777
|
-
];
|
|
778
|
-
RichTextDirective.ctorParameters = () => [
|
|
779
|
-
{ type: ViewContainerRef },
|
|
780
|
-
{ type: TemplateRef }
|
|
781
|
-
];
|
|
782
|
-
RichTextDirective.propDecorators = {
|
|
783
|
-
editable: [{ type: Input, args: ['scRichTextEditable',] }],
|
|
784
|
-
field: [{ type: Input, args: ['scRichText',] }]
|
|
747
|
+
class RichTextDirective {
|
|
748
|
+
constructor(viewContainer, templateRef) {
|
|
749
|
+
this.viewContainer = viewContainer;
|
|
750
|
+
this.templateRef = templateRef;
|
|
751
|
+
this.editable = true;
|
|
752
|
+
}
|
|
753
|
+
ngOnChanges(changes) {
|
|
754
|
+
if (changes.field || changes.editable) {
|
|
755
|
+
if (!this.viewRef) {
|
|
756
|
+
this.viewContainer.clear();
|
|
757
|
+
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
758
|
+
}
|
|
759
|
+
this.updateView();
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
updateView() {
|
|
763
|
+
const field = this.field;
|
|
764
|
+
if (!field || (!field.editable && !field.value)) {
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
const html = field.editable && this.editable ? field.editable : field.value;
|
|
768
|
+
this.viewRef.rootNodes.forEach((node) => {
|
|
769
|
+
node.innerHTML = html;
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
RichTextDirective.decorators = [
|
|
774
|
+
{ type: Directive, args: [{
|
|
775
|
+
selector: '[scRichText]',
|
|
776
|
+
},] }
|
|
777
|
+
];
|
|
778
|
+
RichTextDirective.ctorParameters = () => [
|
|
779
|
+
{ type: ViewContainerRef },
|
|
780
|
+
{ type: TemplateRef }
|
|
781
|
+
];
|
|
782
|
+
RichTextDirective.propDecorators = {
|
|
783
|
+
editable: [{ type: Input, args: ['scRichTextEditable',] }],
|
|
784
|
+
field: [{ type: Input, args: ['scRichText',] }]
|
|
785
785
|
};
|
|
786
786
|
|
|
787
|
-
class TextDirective {
|
|
788
|
-
constructor(viewContainer, templateRef) {
|
|
789
|
-
this.viewContainer = viewContainer;
|
|
790
|
-
this.templateRef = templateRef;
|
|
791
|
-
this.editable = true;
|
|
792
|
-
this.encode = true;
|
|
793
|
-
}
|
|
794
|
-
ngOnChanges(changes) {
|
|
795
|
-
if (changes.field || changes.editable || changes.encode) {
|
|
796
|
-
if (!this.viewRef) {
|
|
797
|
-
this.viewContainer.clear();
|
|
798
|
-
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
799
|
-
}
|
|
800
|
-
this.updateView();
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
updateView() {
|
|
804
|
-
const field = this.field;
|
|
805
|
-
let editable = this.editable;
|
|
806
|
-
if (!field || (!field.editable && (field.value === undefined || field.value === ''))) {
|
|
807
|
-
return;
|
|
808
|
-
}
|
|
809
|
-
// can't use editable value if we want to output unencoded
|
|
810
|
-
if (!this.encode) {
|
|
811
|
-
editable = false;
|
|
812
|
-
}
|
|
813
|
-
const html = field.editable && editable ? field.editable : field.value;
|
|
814
|
-
const setDangerously = (field.editable && editable) || !this.encode;
|
|
815
|
-
this.viewRef.rootNodes.forEach((node) => {
|
|
816
|
-
if (setDangerously) {
|
|
817
|
-
node.innerHTML = html;
|
|
818
|
-
}
|
|
819
|
-
else {
|
|
820
|
-
node.textContent = html;
|
|
821
|
-
}
|
|
822
|
-
});
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
TextDirective.decorators = [
|
|
826
|
-
{ type: Directive, args: [{
|
|
827
|
-
selector: '[scText]',
|
|
828
|
-
},] }
|
|
829
|
-
];
|
|
830
|
-
TextDirective.ctorParameters = () => [
|
|
831
|
-
{ type: ViewContainerRef },
|
|
832
|
-
{ type: TemplateRef }
|
|
833
|
-
];
|
|
834
|
-
TextDirective.propDecorators = {
|
|
835
|
-
editable: [{ type: Input, args: ['scTextEditable',] }],
|
|
836
|
-
encode: [{ type: Input, args: ['scTextEncode',] }],
|
|
837
|
-
field: [{ type: Input, args: ['scText',] }]
|
|
787
|
+
class TextDirective {
|
|
788
|
+
constructor(viewContainer, templateRef) {
|
|
789
|
+
this.viewContainer = viewContainer;
|
|
790
|
+
this.templateRef = templateRef;
|
|
791
|
+
this.editable = true;
|
|
792
|
+
this.encode = true;
|
|
793
|
+
}
|
|
794
|
+
ngOnChanges(changes) {
|
|
795
|
+
if (changes.field || changes.editable || changes.encode) {
|
|
796
|
+
if (!this.viewRef) {
|
|
797
|
+
this.viewContainer.clear();
|
|
798
|
+
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
799
|
+
}
|
|
800
|
+
this.updateView();
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
updateView() {
|
|
804
|
+
const field = this.field;
|
|
805
|
+
let editable = this.editable;
|
|
806
|
+
if (!field || (!field.editable && (field.value === undefined || field.value === ''))) {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
// can't use editable value if we want to output unencoded
|
|
810
|
+
if (!this.encode) {
|
|
811
|
+
editable = false;
|
|
812
|
+
}
|
|
813
|
+
const html = field.editable && editable ? field.editable : field.value;
|
|
814
|
+
const setDangerously = (field.editable && editable) || !this.encode;
|
|
815
|
+
this.viewRef.rootNodes.forEach((node) => {
|
|
816
|
+
if (setDangerously) {
|
|
817
|
+
node.innerHTML = html;
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
node.textContent = html;
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
TextDirective.decorators = [
|
|
826
|
+
{ type: Directive, args: [{
|
|
827
|
+
selector: '[scText]',
|
|
828
|
+
},] }
|
|
829
|
+
];
|
|
830
|
+
TextDirective.ctorParameters = () => [
|
|
831
|
+
{ type: ViewContainerRef },
|
|
832
|
+
{ type: TemplateRef }
|
|
833
|
+
];
|
|
834
|
+
TextDirective.propDecorators = {
|
|
835
|
+
editable: [{ type: Input, args: ['scTextEditable',] }],
|
|
836
|
+
encode: [{ type: Input, args: ['scTextEncode',] }],
|
|
837
|
+
field: [{ type: Input, args: ['scText',] }]
|
|
838
838
|
};
|
|
839
839
|
|
|
840
|
-
class LayoutServiceError {
|
|
840
|
+
class LayoutServiceError {
|
|
841
841
|
}
|
|
842
842
|
|
|
843
|
-
// TODO: these are deprecated and we should switch to using new methods
|
|
844
|
-
const { fetchRouteData, fetchPlaceholderData } = dataApi;
|
|
845
|
-
class LayoutService {
|
|
846
|
-
static getLayoutServiceError(error) {
|
|
847
|
-
const layoutServiceError = new LayoutServiceError();
|
|
848
|
-
const response = error.response;
|
|
849
|
-
if (response) {
|
|
850
|
-
layoutServiceError.status = response.status;
|
|
851
|
-
layoutServiceError.statusText = response.statusText;
|
|
852
|
-
layoutServiceError.data = response.data;
|
|
853
|
-
}
|
|
854
|
-
return throwError(layoutServiceError);
|
|
855
|
-
}
|
|
856
|
-
getRouteData(route, options) {
|
|
857
|
-
return from(fetchRouteData(route, options)).pipe(catchError(LayoutService.getLayoutServiceError));
|
|
858
|
-
}
|
|
859
|
-
getPlaceholderData(route, placeholderName, options) {
|
|
860
|
-
return from(fetchPlaceholderData(placeholderName, route, options)).pipe(catchError(LayoutService.getLayoutServiceError));
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
LayoutService.decorators = [
|
|
864
|
-
{ type: Injectable }
|
|
843
|
+
// TODO: these are deprecated and we should switch to using new methods
|
|
844
|
+
const { fetchRouteData, fetchPlaceholderData } = dataApi;
|
|
845
|
+
class LayoutService {
|
|
846
|
+
static getLayoutServiceError(error) {
|
|
847
|
+
const layoutServiceError = new LayoutServiceError();
|
|
848
|
+
const response = error.response;
|
|
849
|
+
if (response) {
|
|
850
|
+
layoutServiceError.status = response.status;
|
|
851
|
+
layoutServiceError.statusText = response.statusText;
|
|
852
|
+
layoutServiceError.data = response.data;
|
|
853
|
+
}
|
|
854
|
+
return throwError(layoutServiceError);
|
|
855
|
+
}
|
|
856
|
+
getRouteData(route, options) {
|
|
857
|
+
return from(fetchRouteData(route, options)).pipe(catchError(LayoutService.getLayoutServiceError));
|
|
858
|
+
}
|
|
859
|
+
getPlaceholderData(route, placeholderName, options) {
|
|
860
|
+
return from(fetchPlaceholderData(placeholderName, route, options)).pipe(catchError(LayoutService.getLayoutServiceError));
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
LayoutService.decorators = [
|
|
864
|
+
{ type: Injectable }
|
|
865
865
|
];
|
|
866
866
|
|
|
867
|
-
class DateDirective {
|
|
868
|
-
constructor(viewContainer, templateRef, datePipe) {
|
|
869
|
-
this.viewContainer = viewContainer;
|
|
870
|
-
this.templateRef = templateRef;
|
|
871
|
-
this.datePipe = datePipe;
|
|
872
|
-
this.editable = true;
|
|
873
|
-
}
|
|
874
|
-
ngOnChanges(changes) {
|
|
875
|
-
if (changes.field || changes.format) {
|
|
876
|
-
if (!this.viewRef) {
|
|
877
|
-
this.viewContainer.clear();
|
|
878
|
-
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
879
|
-
}
|
|
880
|
-
this.updateView();
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
updateView() {
|
|
884
|
-
const field = this.field;
|
|
885
|
-
if (!field || (!field.editable && !field.value)) {
|
|
886
|
-
return;
|
|
887
|
-
}
|
|
888
|
-
const html = field.editable && this.editable ? field.editable : field.value;
|
|
889
|
-
const setDangerously = field.editable && this.editable;
|
|
890
|
-
this.viewRef.rootNodes.forEach((node) => {
|
|
891
|
-
if (setDangerously) {
|
|
892
|
-
node.innerHTML = html;
|
|
893
|
-
}
|
|
894
|
-
else {
|
|
895
|
-
node.textContent = this.datePipe.transform(html, this.format, this.timezone, this.locale);
|
|
896
|
-
}
|
|
897
|
-
});
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
DateDirective.decorators = [
|
|
901
|
-
{ type: Directive, args: [{
|
|
902
|
-
selector: '[scDate]',
|
|
903
|
-
},] }
|
|
904
|
-
];
|
|
905
|
-
DateDirective.ctorParameters = () => [
|
|
906
|
-
{ type: ViewContainerRef },
|
|
907
|
-
{ type: TemplateRef },
|
|
908
|
-
{ type: DatePipe }
|
|
909
|
-
];
|
|
910
|
-
DateDirective.propDecorators = {
|
|
911
|
-
format: [{ type: Input, args: ['scDateFormat',] }],
|
|
912
|
-
timezone: [{ type: Input, args: ['scDateTimezone',] }],
|
|
913
|
-
locale: [{ type: Input, args: ['scDateLocale',] }],
|
|
914
|
-
editable: [{ type: Input, args: ['scDateEditable',] }],
|
|
915
|
-
field: [{ type: Input, args: ['scDate',] }]
|
|
867
|
+
class DateDirective {
|
|
868
|
+
constructor(viewContainer, templateRef, datePipe) {
|
|
869
|
+
this.viewContainer = viewContainer;
|
|
870
|
+
this.templateRef = templateRef;
|
|
871
|
+
this.datePipe = datePipe;
|
|
872
|
+
this.editable = true;
|
|
873
|
+
}
|
|
874
|
+
ngOnChanges(changes) {
|
|
875
|
+
if (changes.field || changes.format) {
|
|
876
|
+
if (!this.viewRef) {
|
|
877
|
+
this.viewContainer.clear();
|
|
878
|
+
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
|
879
|
+
}
|
|
880
|
+
this.updateView();
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
updateView() {
|
|
884
|
+
const field = this.field;
|
|
885
|
+
if (!field || (!field.editable && !field.value)) {
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
const html = field.editable && this.editable ? field.editable : field.value;
|
|
889
|
+
const setDangerously = field.editable && this.editable;
|
|
890
|
+
this.viewRef.rootNodes.forEach((node) => {
|
|
891
|
+
if (setDangerously) {
|
|
892
|
+
node.innerHTML = html;
|
|
893
|
+
}
|
|
894
|
+
else {
|
|
895
|
+
node.textContent = this.datePipe.transform(html, this.format, this.timezone, this.locale);
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
DateDirective.decorators = [
|
|
901
|
+
{ type: Directive, args: [{
|
|
902
|
+
selector: '[scDate]',
|
|
903
|
+
},] }
|
|
904
|
+
];
|
|
905
|
+
DateDirective.ctorParameters = () => [
|
|
906
|
+
{ type: ViewContainerRef },
|
|
907
|
+
{ type: TemplateRef },
|
|
908
|
+
{ type: DatePipe }
|
|
909
|
+
];
|
|
910
|
+
DateDirective.propDecorators = {
|
|
911
|
+
format: [{ type: Input, args: ['scDateFormat',] }],
|
|
912
|
+
timezone: [{ type: Input, args: ['scDateTimezone',] }],
|
|
913
|
+
locale: [{ type: Input, args: ['scDateLocale',] }],
|
|
914
|
+
editable: [{ type: Input, args: ['scDateEditable',] }],
|
|
915
|
+
field: [{ type: Input, args: ['scDate',] }]
|
|
916
916
|
};
|
|
917
917
|
|
|
918
|
-
class MissingComponentComponent {
|
|
919
|
-
}
|
|
920
|
-
MissingComponentComponent.decorators = [
|
|
921
|
-
{ type: Component, args: [{
|
|
922
|
-
selector: 'sc-missing-component',
|
|
918
|
+
class MissingComponentComponent {
|
|
919
|
+
}
|
|
920
|
+
MissingComponentComponent.decorators = [
|
|
921
|
+
{ type: Component, args: [{
|
|
922
|
+
selector: 'sc-missing-component',
|
|
923
923
|
template: `
|
|
924
924
|
<div
|
|
925
925
|
style="background: darkorange; outline: 5px solid orange; padding: 10px; color: white; max-width: 500px;"
|
|
@@ -927,230 +927,230 @@ MissingComponentComponent.decorators = [
|
|
|
927
927
|
<h2>{{ rendering.componentName }}</h2>
|
|
928
928
|
<p>JSS component is missing Angular component implementation.</p>
|
|
929
929
|
</div>
|
|
930
|
-
`
|
|
931
|
-
},] }
|
|
932
|
-
];
|
|
933
|
-
MissingComponentComponent.propDecorators = {
|
|
934
|
-
rendering: [{ type: Input }]
|
|
930
|
+
`
|
|
931
|
+
},] }
|
|
932
|
+
];
|
|
933
|
+
MissingComponentComponent.propDecorators = {
|
|
934
|
+
rendering: [{ type: Input }]
|
|
935
935
|
};
|
|
936
936
|
|
|
937
|
-
/**
|
|
938
|
-
* Renders a single JSS component given a rendering definition.
|
|
939
|
-
* Useful inside templated placeholders.
|
|
940
|
-
*/
|
|
941
|
-
class RenderComponentComponent {
|
|
942
|
-
constructor(componentFactoryResolver, differs, componentFactory, missingComponentComponent) {
|
|
943
|
-
this.componentFactoryResolver = componentFactoryResolver;
|
|
944
|
-
this.differs = differs;
|
|
945
|
-
this.componentFactory = componentFactory;
|
|
946
|
-
this.missingComponentComponent = missingComponentComponent;
|
|
947
|
-
this.destroyed = false;
|
|
948
|
-
}
|
|
949
|
-
set inputs(value) {
|
|
950
|
-
this._inputs = value;
|
|
951
|
-
if (!this._differ && value) {
|
|
952
|
-
this._differ = this.differs.find(value).create();
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
ngOnChanges(changes) {
|
|
956
|
-
if (changes.rendering) {
|
|
957
|
-
this._render();
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
_setComponentInputs(componentInstance, inputs) {
|
|
961
|
-
Object.entries(inputs).forEach(([input, inputValue]) => (componentInstance[input] = inputValue));
|
|
962
|
-
}
|
|
963
|
-
_subscribeComponentOutputs(componentInstance, outputs) {
|
|
964
|
-
Object.keys(outputs)
|
|
965
|
-
.filter((output) => componentInstance[output] && componentInstance[output] instanceof Observable)
|
|
966
|
-
.forEach((output) => componentInstance[output]
|
|
967
|
-
.pipe(takeWhile(() => !this.destroyed))
|
|
968
|
-
.subscribe(outputs[output]));
|
|
969
|
-
}
|
|
970
|
-
_render() {
|
|
971
|
-
this.view.clear();
|
|
972
|
-
if (!this.rendering) {
|
|
973
|
-
return;
|
|
974
|
-
}
|
|
975
|
-
const resolveComponent = isRawRendering(this.rendering)
|
|
976
|
-
? Promise.resolve({
|
|
977
|
-
componentImplementation: RawComponent,
|
|
978
|
-
componentDefinition: this.rendering,
|
|
979
|
-
})
|
|
980
|
-
: this.componentFactory.getComponent(this.rendering);
|
|
981
|
-
resolveComponent.then((rendering) => {
|
|
982
|
-
if (!rendering.componentImplementation) {
|
|
983
|
-
const componentName = rendering.componentDefinition.componentName;
|
|
937
|
+
/**
|
|
938
|
+
* Renders a single JSS component given a rendering definition.
|
|
939
|
+
* Useful inside templated placeholders.
|
|
940
|
+
*/
|
|
941
|
+
class RenderComponentComponent {
|
|
942
|
+
constructor(componentFactoryResolver, differs, componentFactory, missingComponentComponent) {
|
|
943
|
+
this.componentFactoryResolver = componentFactoryResolver;
|
|
944
|
+
this.differs = differs;
|
|
945
|
+
this.componentFactory = componentFactory;
|
|
946
|
+
this.missingComponentComponent = missingComponentComponent;
|
|
947
|
+
this.destroyed = false;
|
|
948
|
+
}
|
|
949
|
+
set inputs(value) {
|
|
950
|
+
this._inputs = value;
|
|
951
|
+
if (!this._differ && value) {
|
|
952
|
+
this._differ = this.differs.find(value).create();
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
ngOnChanges(changes) {
|
|
956
|
+
if (changes.rendering) {
|
|
957
|
+
this._render();
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
_setComponentInputs(componentInstance, inputs) {
|
|
961
|
+
Object.entries(inputs).forEach(([input, inputValue]) => (componentInstance[input] = inputValue));
|
|
962
|
+
}
|
|
963
|
+
_subscribeComponentOutputs(componentInstance, outputs) {
|
|
964
|
+
Object.keys(outputs)
|
|
965
|
+
.filter((output) => componentInstance[output] && componentInstance[output] instanceof Observable)
|
|
966
|
+
.forEach((output) => componentInstance[output]
|
|
967
|
+
.pipe(takeWhile(() => !this.destroyed))
|
|
968
|
+
.subscribe(outputs[output]));
|
|
969
|
+
}
|
|
970
|
+
_render() {
|
|
971
|
+
this.view.clear();
|
|
972
|
+
if (!this.rendering) {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
const resolveComponent = isRawRendering(this.rendering)
|
|
976
|
+
? Promise.resolve({
|
|
977
|
+
componentImplementation: RawComponent,
|
|
978
|
+
componentDefinition: this.rendering,
|
|
979
|
+
})
|
|
980
|
+
: this.componentFactory.getComponent(this.rendering);
|
|
981
|
+
resolveComponent.then((rendering) => {
|
|
982
|
+
if (!rendering.componentImplementation) {
|
|
983
|
+
const componentName = rendering.componentDefinition.componentName;
|
|
984
984
|
console.error(`Attempted to render unknown component ${componentName}.`, `Ensure component is mapped, like:
|
|
985
985
|
JssModule.withComponents([
|
|
986
986
|
{ name: '${componentName}', type: ${componentName}Component }
|
|
987
|
-
])`);
|
|
988
|
-
rendering.componentImplementation = this.missingComponentComponent;
|
|
989
|
-
}
|
|
990
|
-
const componentFactory = rendering.componentFactory ||
|
|
991
|
-
this.componentFactoryResolver.resolveComponentFactory(rendering.componentImplementation);
|
|
992
|
-
const componentInstance = this.view.createComponent(componentFactory, 0).instance;
|
|
993
|
-
componentInstance.rendering = rendering.componentDefinition;
|
|
994
|
-
if (this._inputs) {
|
|
995
|
-
this._setComponentInputs(componentInstance, this._inputs);
|
|
996
|
-
}
|
|
997
|
-
if (this.outputs) {
|
|
998
|
-
this._subscribeComponentOutputs(componentInstance, this.outputs);
|
|
999
|
-
}
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
RenderComponentComponent.decorators = [
|
|
1004
|
-
{ type: Component, args: [{
|
|
1005
|
-
selector: 'sc-render-component',
|
|
987
|
+
])`);
|
|
988
|
+
rendering.componentImplementation = this.missingComponentComponent;
|
|
989
|
+
}
|
|
990
|
+
const componentFactory = rendering.componentFactory ||
|
|
991
|
+
this.componentFactoryResolver.resolveComponentFactory(rendering.componentImplementation);
|
|
992
|
+
const componentInstance = this.view.createComponent(componentFactory, 0).instance;
|
|
993
|
+
componentInstance.rendering = rendering.componentDefinition;
|
|
994
|
+
if (this._inputs) {
|
|
995
|
+
this._setComponentInputs(componentInstance, this._inputs);
|
|
996
|
+
}
|
|
997
|
+
if (this.outputs) {
|
|
998
|
+
this._subscribeComponentOutputs(componentInstance, this.outputs);
|
|
999
|
+
}
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
RenderComponentComponent.decorators = [
|
|
1004
|
+
{ type: Component, args: [{
|
|
1005
|
+
selector: 'sc-render-component',
|
|
1006
1006
|
template: `
|
|
1007
1007
|
<ng-template #view></ng-template>
|
|
1008
|
-
`
|
|
1009
|
-
},] }
|
|
1010
|
-
];
|
|
1011
|
-
RenderComponentComponent.ctorParameters = () => [
|
|
1012
|
-
{ type: ComponentFactoryResolver },
|
|
1013
|
-
{ type: KeyValueDiffers },
|
|
1014
|
-
{ type: JssComponentFactoryService },
|
|
1015
|
-
{ type: Type, decorators: [{ type: Inject, args: [PLACEHOLDER_MISSING_COMPONENT_COMPONENT,] }] }
|
|
1016
|
-
];
|
|
1017
|
-
RenderComponentComponent.propDecorators = {
|
|
1018
|
-
rendering: [{ type: Input }],
|
|
1019
|
-
outputs: [{ type: Input }],
|
|
1020
|
-
view: [{ type: ViewChild, args: ['view', { read: ViewContainerRef, static: true },] }],
|
|
1021
|
-
inputs: [{ type: Input }]
|
|
1008
|
+
`
|
|
1009
|
+
},] }
|
|
1010
|
+
];
|
|
1011
|
+
RenderComponentComponent.ctorParameters = () => [
|
|
1012
|
+
{ type: ComponentFactoryResolver },
|
|
1013
|
+
{ type: KeyValueDiffers },
|
|
1014
|
+
{ type: JssComponentFactoryService },
|
|
1015
|
+
{ type: Type, decorators: [{ type: Inject, args: [PLACEHOLDER_MISSING_COMPONENT_COMPONENT,] }] }
|
|
1016
|
+
];
|
|
1017
|
+
RenderComponentComponent.propDecorators = {
|
|
1018
|
+
rendering: [{ type: Input }],
|
|
1019
|
+
outputs: [{ type: Input }],
|
|
1020
|
+
view: [{ type: ViewChild, args: ['view', { read: ViewContainerRef, static: true },] }],
|
|
1021
|
+
inputs: [{ type: Input }]
|
|
1022
1022
|
};
|
|
1023
1023
|
|
|
1024
|
-
class JssModule {
|
|
1025
|
-
/**
|
|
1026
|
-
* Instantiates the JSS module with no component factory.
|
|
1027
|
-
* Useful for using it from libraries. Most of the time you'd want withComponents()
|
|
1028
|
-
* @returns {ModuleWithProviders<JssModule>} module
|
|
1029
|
-
*/
|
|
1030
|
-
static forRoot() {
|
|
1031
|
-
return {
|
|
1032
|
-
ngModule: JssModule,
|
|
1033
|
-
providers: [LayoutService, DatePipe, JssComponentFactoryService],
|
|
1034
|
-
};
|
|
1035
|
-
}
|
|
1036
|
-
/**
|
|
1037
|
-
* Instantiates a module for a lazy-loaded JSS component
|
|
1038
|
-
* @param {Type<any>} component
|
|
1039
|
-
* @returns {ModuleWithProviders<JssModule>} module
|
|
1040
|
-
*/
|
|
1041
|
-
static forChild(component) {
|
|
1042
|
-
return {
|
|
1043
|
-
ngModule: JssModule,
|
|
1044
|
-
providers: [
|
|
1045
|
-
{ provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: component, multi: true },
|
|
1046
|
-
{ provide: ROUTES, useValue: [], multi: true },
|
|
1047
|
-
{ provide: DYNAMIC_COMPONENT, useValue: component },
|
|
1048
|
-
],
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
/**
|
|
1052
|
-
* Instantiates the JSS module and specifies the mapping from component name to component implementation.
|
|
1053
|
-
* Appropriate when defining the set of JSS components that your app is aware of.
|
|
1054
|
-
* @param {ComponentNameAndType[]} components
|
|
1055
|
-
* @param {ComponentNameAndModule[]} [lazyComponents]
|
|
1056
|
-
* @returns {ModuleWithProviders<JssModule>} module
|
|
1057
|
-
*/
|
|
1058
|
-
static withComponents(components, lazyComponents) {
|
|
1059
|
-
return {
|
|
1060
|
-
ngModule: JssModule,
|
|
1061
|
-
providers: [
|
|
1062
|
-
{
|
|
1063
|
-
provide: ANALYZE_FOR_ENTRY_COMPONENTS,
|
|
1064
|
-
useValue: components,
|
|
1065
|
-
multi: true,
|
|
1066
|
-
},
|
|
1067
|
-
{ provide: PLACEHOLDER_COMPONENTS, useValue: components },
|
|
1068
|
-
{ provide: PLACEHOLDER_LAZY_COMPONENTS, useValue: lazyComponents || [] },
|
|
1069
|
-
{ provide: ROUTES, useValue: lazyComponents || [], multi: true },
|
|
1070
|
-
{ provide: PLACEHOLDER_MISSING_COMPONENT_COMPONENT, useValue: MissingComponentComponent },
|
|
1071
|
-
...JssModule.forRoot().providers,
|
|
1072
|
-
],
|
|
1073
|
-
};
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
JssModule.decorators = [
|
|
1077
|
-
{ type: NgModule, args: [{
|
|
1078
|
-
imports: [CommonModule],
|
|
1079
|
-
declarations: [
|
|
1080
|
-
FileDirective,
|
|
1081
|
-
ImageDirective,
|
|
1082
|
-
LinkDirective,
|
|
1083
|
-
RouterLinkDirective,
|
|
1084
|
-
GenericLinkDirective,
|
|
1085
|
-
DateDirective,
|
|
1086
|
-
RenderEachDirective,
|
|
1087
|
-
RenderEmptyDirective,
|
|
1088
|
-
PlaceholderLoadingDirective,
|
|
1089
|
-
RenderComponentComponent,
|
|
1090
|
-
PlaceholderComponent,
|
|
1091
|
-
RawComponent,
|
|
1092
|
-
RichTextDirective,
|
|
1093
|
-
TextDirective,
|
|
1094
|
-
MissingComponentComponent,
|
|
1095
|
-
],
|
|
1096
|
-
exports: [
|
|
1097
|
-
FileDirective,
|
|
1098
|
-
ImageDirective,
|
|
1099
|
-
DateDirective,
|
|
1100
|
-
LinkDirective,
|
|
1101
|
-
RouterLinkDirective,
|
|
1102
|
-
GenericLinkDirective,
|
|
1103
|
-
RenderEachDirective,
|
|
1104
|
-
RenderEmptyDirective,
|
|
1105
|
-
RenderComponentComponent,
|
|
1106
|
-
PlaceholderComponent,
|
|
1107
|
-
PlaceholderLoadingDirective,
|
|
1108
|
-
RichTextDirective,
|
|
1109
|
-
TextDirective,
|
|
1110
|
-
],
|
|
1111
|
-
entryComponents: [RawComponent, MissingComponentComponent],
|
|
1112
|
-
},] }
|
|
1024
|
+
class JssModule {
|
|
1025
|
+
/**
|
|
1026
|
+
* Instantiates the JSS module with no component factory.
|
|
1027
|
+
* Useful for using it from libraries. Most of the time you'd want withComponents()
|
|
1028
|
+
* @returns {ModuleWithProviders<JssModule>} module
|
|
1029
|
+
*/
|
|
1030
|
+
static forRoot() {
|
|
1031
|
+
return {
|
|
1032
|
+
ngModule: JssModule,
|
|
1033
|
+
providers: [LayoutService, DatePipe, JssComponentFactoryService],
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* Instantiates a module for a lazy-loaded JSS component
|
|
1038
|
+
* @param {Type<any>} component
|
|
1039
|
+
* @returns {ModuleWithProviders<JssModule>} module
|
|
1040
|
+
*/
|
|
1041
|
+
static forChild(component) {
|
|
1042
|
+
return {
|
|
1043
|
+
ngModule: JssModule,
|
|
1044
|
+
providers: [
|
|
1045
|
+
{ provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: component, multi: true },
|
|
1046
|
+
{ provide: ROUTES, useValue: [], multi: true },
|
|
1047
|
+
{ provide: DYNAMIC_COMPONENT, useValue: component },
|
|
1048
|
+
],
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Instantiates the JSS module and specifies the mapping from component name to component implementation.
|
|
1053
|
+
* Appropriate when defining the set of JSS components that your app is aware of.
|
|
1054
|
+
* @param {ComponentNameAndType[]} components
|
|
1055
|
+
* @param {ComponentNameAndModule[]} [lazyComponents]
|
|
1056
|
+
* @returns {ModuleWithProviders<JssModule>} module
|
|
1057
|
+
*/
|
|
1058
|
+
static withComponents(components, lazyComponents) {
|
|
1059
|
+
return {
|
|
1060
|
+
ngModule: JssModule,
|
|
1061
|
+
providers: [
|
|
1062
|
+
{
|
|
1063
|
+
provide: ANALYZE_FOR_ENTRY_COMPONENTS,
|
|
1064
|
+
useValue: components,
|
|
1065
|
+
multi: true,
|
|
1066
|
+
},
|
|
1067
|
+
{ provide: PLACEHOLDER_COMPONENTS, useValue: components },
|
|
1068
|
+
{ provide: PLACEHOLDER_LAZY_COMPONENTS, useValue: lazyComponents || [] },
|
|
1069
|
+
{ provide: ROUTES, useValue: lazyComponents || [], multi: true },
|
|
1070
|
+
{ provide: PLACEHOLDER_MISSING_COMPONENT_COMPONENT, useValue: MissingComponentComponent },
|
|
1071
|
+
...JssModule.forRoot().providers,
|
|
1072
|
+
],
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
JssModule.decorators = [
|
|
1077
|
+
{ type: NgModule, args: [{
|
|
1078
|
+
imports: [CommonModule],
|
|
1079
|
+
declarations: [
|
|
1080
|
+
FileDirective,
|
|
1081
|
+
ImageDirective,
|
|
1082
|
+
LinkDirective,
|
|
1083
|
+
RouterLinkDirective,
|
|
1084
|
+
GenericLinkDirective,
|
|
1085
|
+
DateDirective,
|
|
1086
|
+
RenderEachDirective,
|
|
1087
|
+
RenderEmptyDirective,
|
|
1088
|
+
PlaceholderLoadingDirective,
|
|
1089
|
+
RenderComponentComponent,
|
|
1090
|
+
PlaceholderComponent,
|
|
1091
|
+
RawComponent,
|
|
1092
|
+
RichTextDirective,
|
|
1093
|
+
TextDirective,
|
|
1094
|
+
MissingComponentComponent,
|
|
1095
|
+
],
|
|
1096
|
+
exports: [
|
|
1097
|
+
FileDirective,
|
|
1098
|
+
ImageDirective,
|
|
1099
|
+
DateDirective,
|
|
1100
|
+
LinkDirective,
|
|
1101
|
+
RouterLinkDirective,
|
|
1102
|
+
GenericLinkDirective,
|
|
1103
|
+
RenderEachDirective,
|
|
1104
|
+
RenderEmptyDirective,
|
|
1105
|
+
RenderComponentComponent,
|
|
1106
|
+
PlaceholderComponent,
|
|
1107
|
+
PlaceholderLoadingDirective,
|
|
1108
|
+
RichTextDirective,
|
|
1109
|
+
TextDirective,
|
|
1110
|
+
],
|
|
1111
|
+
entryComponents: [RawComponent, MissingComponentComponent],
|
|
1112
|
+
},] }
|
|
1113
1113
|
];
|
|
1114
1114
|
|
|
1115
|
-
/**
|
|
1116
|
-
* @description in Experience Editor with an Angular sample app, anchor tags
|
|
1117
|
-
* with both onclick and href attributes will use the href, blocking the onclick from firing.
|
|
1118
|
-
* This function makes it so the anchor tags function as intended in an Angular sample when using Experience Editor
|
|
1119
|
-
*
|
|
1120
|
-
* The Mutation Observer API is used to observe changes to the body, then select all elements with href="#" and an onclick,
|
|
1121
|
-
* and replaces the # value with javascript:void(0); which prevents the anchor tag from blocking the onclick event handler.
|
|
1122
|
-
* @see Mutation Observer API: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver
|
|
1123
|
-
*/
|
|
1124
|
-
const handleEditorAnchors = () => {
|
|
1125
|
-
// Angular gives the href attribute priority over the onclick attribute if both are present, so we must replace
|
|
1126
|
-
// the href attribute to avoid overriding the onclick in Experience Editor
|
|
1127
|
-
if (!window || !isExperienceEditorActive()) {
|
|
1128
|
-
return;
|
|
1129
|
-
}
|
|
1130
|
-
const targetNode = document.querySelector('body');
|
|
1131
|
-
const callback = (mutationList) => {
|
|
1132
|
-
mutationList.forEach((mutation) => {
|
|
1133
|
-
const btns = document.querySelectorAll('.scChromeDropDown > a[href="#"], a[onclick]');
|
|
1134
|
-
if (mutation.type === 'childList') {
|
|
1135
|
-
btns.forEach((link) => {
|
|
1136
|
-
link.href = 'javascript:void(0);';
|
|
1137
|
-
});
|
|
1138
|
-
}
|
|
1139
|
-
return;
|
|
1140
|
-
});
|
|
1141
|
-
};
|
|
1142
|
-
const observer = new MutationObserver(callback);
|
|
1143
|
-
const observerOptions = {
|
|
1144
|
-
childList: true,
|
|
1145
|
-
subtree: true,
|
|
1146
|
-
};
|
|
1147
|
-
if (targetNode) {
|
|
1148
|
-
observer.observe(targetNode, observerOptions);
|
|
1149
|
-
}
|
|
1115
|
+
/**
|
|
1116
|
+
* @description in Experience Editor with an Angular sample app, anchor tags
|
|
1117
|
+
* with both onclick and href attributes will use the href, blocking the onclick from firing.
|
|
1118
|
+
* This function makes it so the anchor tags function as intended in an Angular sample when using Experience Editor
|
|
1119
|
+
*
|
|
1120
|
+
* The Mutation Observer API is used to observe changes to the body, then select all elements with href="#" and an onclick,
|
|
1121
|
+
* and replaces the # value with javascript:void(0); which prevents the anchor tag from blocking the onclick event handler.
|
|
1122
|
+
* @see Mutation Observer API: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver
|
|
1123
|
+
*/
|
|
1124
|
+
const handleEditorAnchors = () => {
|
|
1125
|
+
// Angular gives the href attribute priority over the onclick attribute if both are present, so we must replace
|
|
1126
|
+
// the href attribute to avoid overriding the onclick in Experience Editor
|
|
1127
|
+
if (!window || !isExperienceEditorActive()) {
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
const targetNode = document.querySelector('body');
|
|
1131
|
+
const callback = (mutationList) => {
|
|
1132
|
+
mutationList.forEach((mutation) => {
|
|
1133
|
+
const btns = document.querySelectorAll('.scChromeDropDown > a[href="#"], a[onclick]');
|
|
1134
|
+
if (mutation.type === 'childList') {
|
|
1135
|
+
btns.forEach((link) => {
|
|
1136
|
+
link.href = 'javascript:void(0);';
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
return;
|
|
1140
|
+
});
|
|
1141
|
+
};
|
|
1142
|
+
const observer = new MutationObserver(callback);
|
|
1143
|
+
const observerOptions = {
|
|
1144
|
+
childList: true,
|
|
1145
|
+
subtree: true,
|
|
1146
|
+
};
|
|
1147
|
+
if (targetNode) {
|
|
1148
|
+
observer.observe(targetNode, observerOptions);
|
|
1149
|
+
}
|
|
1150
1150
|
};
|
|
1151
1151
|
|
|
1152
|
-
/**
|
|
1153
|
-
* Generated bundle index. Do not edit.
|
|
1152
|
+
/**
|
|
1153
|
+
* Generated bundle index. Do not edit.
|
|
1154
1154
|
*/
|
|
1155
1155
|
|
|
1156
1156
|
export { ComponentNameAndType, DYNAMIC_COMPONENT, FileDirective, GenericLinkDirective, ImageDirective, JssModule, LayoutService, LayoutServiceError, LinkDirective, PlaceholderComponent, PlaceholderLoadingDirective, RichTextDirective, RouterLinkDirective, TextDirective, handleEditorAnchors, isRawRendering, PLACEHOLDER_COMPONENTS as ɵb, PLACEHOLDER_LAZY_COMPONENTS as ɵc, PLACEHOLDER_MISSING_COMPONENT_COMPONENT as ɵd, RenderEachDirective as ɵe, RenderEmptyDirective as ɵf, JssComponentFactoryService as ɵg, DateDirective as ɵh, RenderComponentComponent as ɵi, RawComponent as ɵj, MissingComponentComponent as ɵk };
|