I am getting the following error, not sure what to do:
(SystemJS) Unexpected directive
ViewerComponent
imported by the moduleGalleryModule
Thanks for any help relating to what might be causing the error. In the main app it is importing the gallery module. The gallery component has the viewer component as a child.
Gallery Component:
import {Component, NgZone, ViewChild, ElementRef} from '@angular/core';
import {Http, Response} from '@angular/http';
import { ViewerComponent } from '../viewer/viewer.component';
import 'rxjs/Rx';
interface IImage {
url: string;
thumbnail: string;
date: string;
width: number;
height: number;
}
@Component({
selector: 'sd-gallery',
templateUrl: 'gallery.component.html',
styleUrls: ['gallery.component.css']
})
export class GalleryComponent {;
@ViewChild('galleryContainer') galleryContainer: ElementRef;
@ViewChild('asyncLoadingContainer') asyncLoadingContainer: ElementRef;
thumbnailBasePath = 'assets/img/gallery/preview_xxs/';
currentIdx: number = 0;
galleryBasePath: string = 'assets/img/gallery/';
showBig: boolean = false;
images: any[] = [{ url: '' }];
gallery: any[] = [];
imgIterations = 1;
allImagesLoaded = false;
// TypeScript public modifiers
constructor(private _ngZone: NgZone, private http: Http) {
}
private ngAfterContentInit() {
this.fetchDataAndRender();
}
private fetchDataAndRender() {
this.http.get(this.galleryBasePath + 'data.json')
.map((res: Response) => res.json())
.subscribe(
data => {
this.images = data;
this.render();
},
err => console.error(err),
() => undefined);
}
private render() {
let tempRow = [this.images[0]];
let rowIndex = 0;
let i = 0;
for (i; i < this.imgIterations && i < this.images.length; i++) {
while (this.images[i + 1] && this.shouldAddCandidate(tempRow, this.images[i + 1])) {
i++;
}
if (this.images[i + 1]) {
tempRow.pop();
}
this.gallery[rowIndex++] = tempRow;
tempRow = [this.images[i + 1]];
}
this.scaleGallery();
if (i >= this.images.length) {
this.allImagesLoaded = true;
}
else {
this.checkForAsyncReload();
}
}
private shouldAddCandidate(imgRow: IImage[], candidate: IImage): boolean {
let oldDifference = this.calcIdealHeight() - this.calcRowHeight(imgRow);
imgRow.push(candidate);
let newDifference = this.calcIdealHeight() - this.calcRowHeight(imgRow);
return Math.abs(oldDifference) > Math.abs(newDifference);
}
private calcRowHeight(imgRow: IImage[]) {
let xsum = this.calcOriginalRowWidth(imgRow);
let ratio = this.getGalleryWidth() / xsum;
let rowHeight = imgRow[0].height * ratio;
return rowHeight;
}
private scaleGallery() {
this.gallery.forEach((imgRow) => {
let xsum = this.calcOriginalRowWidth(imgRow);
if (imgRow != this.gallery[this.gallery.length - 1]) {
let ratio = this.getGalleryWidth() / xsum;
imgRow.forEach((img: any) => {
img.width = img.width * ratio;
img.height = img.height * ratio;
})
}
})
}
private calcOriginalRowWidth(imgRow: IImage[]) {
let xsum = 0;
imgRow.forEach((img) => {
let individualRatio = this.calcIdealHeight() / img.height;
img.width = img.width * individualRatio;
img.height = this.calcIdealHeight();
xsum += img.width + 1;
});
return xsum;
}
private calcIdealHeight() {
return (this.getGalleryWidth() / 8) + 70;
}
private openImageViewer(img: any) {
this.showBig = undefined;
this.showBig = true;
this.currentIdx = this.images.indexOf(img);
}
private getGalleryWidth() {
if (this.galleryContainer.nativeElement.clientWidth === 0) {
// IE11
return this.galleryContainer.nativeElement.scrollWidth;
}
return this.galleryContainer.nativeElement.clientWidth;
}
private checkForAsyncReload() {
if (!this.allImagesLoaded) {
var loadingDiv: any = this.asyncLoadingContainer.nativeElement;
var elmTop = loadingDiv.getBoundingClientRect().top;
var elmBottom = loadingDiv.getBoundingClientRect().bottom;
var isVisible = (elmTop >= 0) && (elmBottom <= window.innerHeight);
if (isVisible) {
this.imgIterations += 5;
this.fetchDataAndRender();
}
}
}
private onClose() {
this.showBig = false;
}
private onResize() {
this.render();
}
}
Gallery Module:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { ViewerComponent } from '../viewer/viewer.component';
import { GalleryComponent } from './gallery.component';
@NgModule({
imports: [BrowserModule, FormsModule, HttpModule, ViewerComponent],
declarations: [GalleryComponent],
exports: [GalleryModule],
providers: []
})
export class GalleryModule { }
Viewer HTML:
<div class="outerContainer" (window:resize)="onResize($event)" [hidden]="!showViewer">
<img [ngClass]="{'activeArrow': leftArrowActive}" class="arrow left" [src]="arrows[0]" (click)="navigate(-1, false)" [hidden]="!showViewer || !leftArrowVisible" />
<img [ngClass]="{'activeArrow': rightArrowActive}" class="arrow right" [src]="arrows[1]" (click)="navigate(1, false)" [hidden]="!showViewer || !rightArrowVisible" />
<div class="buttonContainer" [hidden]="!showViewer">
<span class="action fullsize" (click)="openFullsize()" [hidden]="!showViewer">100%</span>
<img class="action close" src="assets/img/icon/close.svg" (click)="closeViewer()" [hidden]="!showViewer" />
</div>
<div class="imageContainer" (click)="showNavigationArrows()" (swipeleft)="navigate(1, true)" (swiperight)="navigate(-1, true)" [hidden]="!showViewer">
<img class="image" [src]="previewImagePath" [hidden]="!showViewer" />
</div>
</div>
Viewer Component:
import {Component, NgZone, ViewChild, ElementRef, Input, Output, EventEmitter} from '@angular/core';
import {Http, Response} from '@angular/http';
import 'rxjs/Rx';
interface IImage {
url: string;
thumbnail: string;
date: string;
width: number;
height: number;
}
@Component({
selector: 'sd-viewer',
templateUrl: 'viewer.component.html',
styleUrls: ['viewer.component.css']
})
// host: {
// '(document:keydown)': 'onKeydown($event)',
// }
export class ViewerComponent {
@Input() images: any[];
@Input() currentIdx: number;
@Input() showViewer: boolean;
@Output() onClose = new EventEmitter<boolean>();
arrows: string[] = ['assets/img/icon/left.svg', 'assets/img/icon/right.svg'];
leftArrowActive: boolean = true;
rightArrowActive: boolean = true;
leftArrowVisible: boolean = true;
rightArrowVisible: boolean = true;
previewImagePath = '';
// TypeScript public modifiers
constructor(private _ngZone: NgZone, private http: Http) {
}
ngOnChanges(changes: any) {
if (this.images[this.currentIdx].name) {
this.updatePreviewImage();
}
}
ngAfterContentInit() {
}
onKeydown(event: KeyboardEvent) {
let prevent = [37, 39, 27]
.find(no => no === event.keyCode);
if (prevent) event.preventDefault();
switch (prevent) {
case 37:
// navigate left
this.navigate(-1, false);
break;
case 39:
// navigate right
this.navigate(1, false);
break;
case 27:
// esc
this.closeViewer();
break;
}
}
updateArrowActivation() {
if (this.currentIdx <= 0) {
this.leftArrowActive = false;
}
else {
this.leftArrowActive = true;
}
if (this.currentIdx >= this.images.length - 1) {
this.rightArrowActive = false;
}
else {
this.rightArrowActive = true;
}
}
/**
* direction (-1: left, 1: right)
* swipe (user swiped)
*/
navigate(direction : number, swipe : boolean) {
if ((direction === 1 && this.currentIdx < this.images.length - 1) ||
(direction === -1 && this.currentIdx > 0)) {
// increases or decreases the counter
this.currentIdx += direction;
if (swipe) {
this.hideNavigationArrows();
}
else {
this.updateArrowActivation();
this.showNavigationArrows();
}
this.updatePreviewImage();
}
}
hideNavigationArrows() {
this.leftArrowVisible = false;
this.rightArrowVisible = false;
}
showNavigationArrows() {
this.leftArrowVisible = true;
this.rightArrowVisible = true;
}
openFullsize() {
window.location.href = 'assets/img/gallery/raw/' + this.images[this.currentIdx].name;
}
private closeViewer() {
this.showViewer = false;
this.onClose.emit(false);
}
private updatePreviewImage() {
let height = window.innerHeight;
let basePath = 'assets/img/gallery/';
if (height <= 375) {
basePath += 'preview_xxs/';
} else if (height <= 768) {
basePath += 'preview_xs/';
} else if (height <= 1080) {
basePath += 'preview_s/';
} else if (height <= 1600) {
basePath += 'preview_m/';
} else if (height <= 2160) {
basePath += 'preview_l/';
} else if (height <= 2880) {
basePath += 'preview_xl/';
} else {
basePath += 'raw';
}
this.previewImagePath = basePath + this.images[this.currentIdx].name;
}
private onResize() {
this.updatePreviewImage();
}
}