#angular

컴포넌트에 safe pipe를 사용할 수 있도록 Pipe를 만든다

1
2
3
4
5
6
7
8
9
10
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer} from '@angular/platform-browser';

@Pipe({ name: 'safe' })
export class SafePipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {}
transform(url) {
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
}
}

app.module에 SafePipe를 선언해 준다.

생성한 pipe를 module에 포함시켜 준다.

1
2
3
4
5
6
@NgModule({
declarations : [
...
SafePipe
],
})

html 작성

iframe을 사용 할 때 src에 safe pipe를 사용한다.

1
<iframe width="100%" height="300" [src]="url | safe"></iframe>

x-frame-options 해결하기

유투브 공유하기 url을 퍼와서 재생하면 x-frame-option to ‘sameorigin’이라는 에러가 발생하게 된다.
여기서 X-Frame-Option이란 http response header의 한 종류로써 자신의 컨텐츠가 ,

이 옵션은 나의 컨텐츠가 다른 사이트에 무단으로 포함되는 것을 막고 다른 사이트를 통해 클릭 공격 등을 시도하는 것을 막을 수 있다.

즉, Youtube가 컨텐츠를 업로드 하는 시점에 x-frame-option을 설정하여 무단으로 퍼갈 수 없도록 하는 것이다.
때문에 Youtube에서 컨텐츠를 가져와 embed 하고 싶은 경우에는 반드시 공유=>퍼가기 를 누르면 나오는 소스코드의 src 부분을
가져와야 한다. 이 url 에 포함된 중간의 embed 라는 문자는 해당 컨텐츠가 다른 사이트 에서도 재생 될 수 있도록 x-frame-option이 지정되어 있기에
퍼가는 것이 가능해 진다.


hmr 이란?

Hot Module Replacement의 약자로 모듈의 변경사항을 실시간으로 어플리케이션에 반영한다.

angular에 environment 추가하기

environment.hmr.ts 파일 만들기

1
2
3
4
export const environment = {
production: false,
hmr: true
};

src/environments/environment.prod.ts 수정하기

1
2
3
4
export const environment = {
production: true,
hmr: false
};

src/environments/environment.ts 수정하기

1
2
3
4
export const environment = {
production: false,
hmr: false
};

angular-cli.json 수정하기

1
2
3
4
5
6
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"hmr": "environments/environment.hmr.ts",
"prod": "environments/environment.prod.ts"
},

package.json 수정하기

1
2
3
4
5
6
7
8
"scripts": {
"start": "ng serve",
"hmr": "ng serve --hmr -e=hmr",
"lint": "tslint \"src/**/*.ts\"",
"test": "ng test",
"pree2e": "webdriver-manager update",
"e2e": "protractor"
}

npm run hmr 명령어를 통해 environment를 적용할 수 있다.

hmr 모듈 import 하기

1
npm install --save-dev @angularclass/hmr

src/hmr.ts 생성하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { NgModuleRef, ApplicationRef } from '@angular/core';
import { createNewHosts } from '@angularclass/hmr';

export const hmrBootstrap = (module: any, bootstrap: () => Promise<NgModuleRef<any>>) => {
let ngModule: NgModuleRef<any>;
module.hot.accept();
bootstrap().then(mod => ngModule = mod);
module.hot.dispose(() => {
const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef);
const elements = appRef.components.map(c => c.location.nativeElement);
const makeVisible = createNewHosts(elements);
ngModule.destroy();
makeVisible();
});
};

src/main.ts 수정하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

import { hmrBootstrap } from './hmr';

if (environment.production) {
enableProdMode();
}

const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);

if (environment.hmr) {
if (module[ 'hot' ]) {
hmrBootstrap(module, bootstrap);
} else {
console.error('HMR is not enabled for webpack-dev-server!');
console.log('Are you using the --hmr flag for ng serve?');
}
} else {
bootstrap();
}

새로운 환경 반영하기

1
npm run hmr

출처


설치하기

1
npm install ngx-infinite-scroll --save

동작 특성

window scroll 이벤트를 감지하여 callback을 발생시킨다.
실제 요소가 스크롤 될때 콜백을 수행하기 위해서는 다음 설정이 되어야 한다.

1
2
[scrollWindow]="false"
set an explict css "height" value to the element

import 하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app';

@NgModule({
imports:[ BrowserModule, InfiniteScrollModule ],
declarations: [ AppComponent, ],
bootstrap: [ AppComponent ]
})
export class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);

아래 예제에서는 스크롤이 내려가면 onScroll 함수가 호출된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { Component } from '@angular/core';

@Component({
selector: 'app',
template: `
<div class="search-results"
infiniteScroll
[infiniteScrollDistance]="2"
[infiniteScrollThrottle]="50"
(scrolled)="onScroll()">
</div>
`
})
export class AppComponent {
onScroll () {
console.log('scrolled!!')
}
}

Host Listener란?

호스트의 이벤트를 감지하는 라이브러리

HostListener Decorator Component 작성

아래와 같이 호스트의 이벤트를 감지한다.
여기서 window는

1
2
3
4
5
6
7
8
9
10
11
12
import { HostListener} from "@angular/core";
import { DOCUMENT } from "@angular/platform-browser";
import { Inject } from "@angular/core";

export class LayoutNavComponent implements OnInit {
constructor(@Inject(DOCUMENT) private document: Document) { }
}
@HostListener("window:scroll", [])
onWindowScroll() {
//we'll do some stuff here when the window is scrolled
let windowScrollPos = this.document.documentElement.scrollTop;
}

observable과 throttle을 활용하여 event 반응하기

throttle time이 200ms인 observable을 생성하고, subject를 통해 새로운 인자값을 전달한다.
생성한 observable을 subscribe 해 주고, subject를 통해 계속해서 새로운 인자값을 전달한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/throttleTime';

export class AppComponent implements OnInit {

private resizeSubject = new Subject<number>();
private resizeObservable = this.resizeSubject.asObservable().throttleTime(200);

@HostListener('window:resize', ['$event.target.innerWidth'])
onResize(width: number) {
this.resizeSubject.next(width);
}

ngOnInit() {
this.resizeObservable.subscribe(x => this.doSomethingWithThrottledEvent(x));
}

private doSomethingWithThrottledEvent(width: number) {
// . . .

}
}

참조

ngx-lazy-load-images 설치하기

1
npm i ngx-lazy-load-images --save

모듈 import 하기

1
2
3
4
5
6
7
8
9
import { NgModule } from '@angular/core';
import { LazyLoadImagesModule } from 'ngx-lazy-load-images';

@NgModule({
imports: [
LazyLoadImagesModule
]
})
export class AppComponent {}

사용하고자 하는 img에 lazy-load-images directive 사용하기

img 태그에 사용하는 것이 아니고 img의 상위 태그에 directive를 넣어야 한다.

1
2
3
4
5
6
7
8
9
<!-- Image tags -->
<div class="image-list" lazy-load-images>
<img *ngFor="let imageUrl in images" [attr.data-src]="imageUrl">
</div>

<!-- Background images -->
<div class="image-list" lazy-load-images>
<div *ngFor="let imageUrl in images" [attr.data-background-src]="imageUrl"></div>
</div>

img 에 data-src 속성 넣기

undefined

참조

angular application을 ie에서 사용할때

ie는 Object.assign()을 지원하지 않기 때문에 polyfill.ts를 사용하여야 한다.

polyfills.ts에는 이미 ie와 사파리 브라우저에서 사용하기 위한 다양한 import가 주석처리 되어 있으므로

이를 주석해제하면 해결할 수 있다.

파이프를 사용하기 위한 intl 설치

1
npm install --save intl

애니메이션 사용을 위한 web-animation설치

1
npm install --save web-animations-js

ngClass 사용을 위한 classlist설치

1
npm install --save classlist.js

server.js 작성

express 에서 socket.io를 실행하기 위해

express.io를 설치한다.

노드 http 서버와 결합시킬 socket.io에 http를 전달하여 initialize한다.

connection 이벤트가 발생하면 특정 동작을 한다.

io.emit을 통해 데이터를 전달한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var io = require('socket.io').listen(server);

io.on('connection', (socket) => {

console.log('user connected');

socket.on('disconnect', function() {
console.log('user disconnected');
});

socket.on('add-message', (message) => {
io.emit('message', { type: 'new-message', text: message });
// Function above that stores the message in the database
databaseStore(message)
});
});

클라이언트에서 socket.io 설치 및 임포트

소켓 io를 라우터에 전달한다.

1
2
3
4
5
6
npm i socket.io-client --save
npm install socket.io --save

const server = http.createServer(app);
var io = require('socket.io').listen(server);
const all = require('./server/routes/all')(mysql, conn, express, io);

angular service

io()는 socket을 반환한다.

socket.emit을 통해 이벤트를 발생시킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import * as io from 'socket.io-client';

@Injectable()
export class ChatService {
private url = 'http://localhost:5000';
private socket;

sendMessage(message){
this.socket.emit('add-message', message);
}

getMessages() {
let observable = new Observable(observer => {
this.socket = io(this.url);
this.socket.on('message', (data) => {
observer.next(data);
});
return () => {
this.socket.disconnect();
};
})
return observable;
}
}

angular component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
messages = [];
connection;
message;

sendMessage(){
this.chatService.sendMessage(this.message);
this.message = '';
}

ngOnInit() {
this.connection = this.chatService.getMessages().subscribe(message => {
this.messages.push(message);
})
}

ngOnDestroy() {
this.connection.unsubscribe();
}

참조
use with router

개요

흔히 bracket 안에 다양한 model을 바인딩 하는 경우 null 혹은 undefined에 대해 많은 에러가 일어나게 된다.

예를 들어 다음과 같은 경우

1
2
3
{% raw %}
{{user.name}}
{% endraw %}

user 안에 값이 없다면 null안에서 name property를 가져올 수 없으므로 전체 어플리케이션에 치명적인 오류가 일어나게 된다.

safe navigation operator의 활용

다음과 같이 Object?.property를 사용하는 경우
Object의 값이 null이어도 시스템 에러를 발생시키지 않아
보다 안전한 프로그램이 될 수 있다.

1
2
3
{% raw %}
{{user?.name}}
{% endraw %}

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×