팡이네

파이프를 변수에 넣어 동적으로 적용시키고자 할 때 사용

 

dynamic-pipe.ts

import { Injector, Pipe, PipeTransform } from '@angular/core';
import { NumberZeroPipe } from './number-zero.pipe';
import { StringZeroPipe } from './string-zero.pipe';

@Pipe({
    name: 'dynamicPipe'
})
export class DynamicPipe implements PipeTransform {

    public constructor(
        private injector: Injector
    ) {
    }

    transform(value: any, pipeToken: any, pipeArgs: any[]): any {
        // 사용할 pipe 선언
        const MAP = {
            'number0': NumberZeroPipe,
            'string0': StringZeroPipe,
        }

        if (pipeToken && MAP.hasOwnProperty(pipeToken)) {
            var pipeClass = MAP[pipeToken];
            var pipe = this.injector.get(pipeClass);
            if (Array.isArray(pipeArgs)) {
                return pipe.transform(value, ...pipeArgs);
            } else {
                return pipe.transform(value, pipeArgs);
            }
        }
        else {
            return value;
        }
    }
}

HTML

<ul>
    <li *ngFor="let item of list">
        {{ item.data | dynamicPipe: item.pipe : item.pipeOptions }}
    </li>
</ul>

TS

this.list = [
	{ data: 1000000.12345, pipe: 'number0', pipeOptions: 'limit: 2' },
	{ data: 2000000.12345, pipe: 'number0', pipeOptions: 'limit: 2' },
];

출처

http:// https://stackoverflow.com/questions/36564976/dynamic-pipe-in-angular-2/46910713#46910713

.html

tr 태그는 포커스가 가능한 태그가 아니기 때문에 tabindex 속성 필요

...
<tr #trOrder tabindex="0">
    <td>...</td>
</tr>
...

.ts

import { ElementRef, QueryList, ViewChildren } from '@angular/core';
...
@ViewChildren('trOrder') trList: QueryList<ElementRef>;
...
setFocus(index) {
    this.trList.get(index).nativeElement.focus();
}

typescript, angular

 

문자열 표시 파이프

//--------------------------------------
// 문자열 표시 파이프
//--------------------------------------
/**
 * 문자열 형식 표시
 * options {
 *     replace: %s를 문자열로 변환하여 표시,
 *     pre:  문자열 앞에 표시
 *     post: 문자열 뒤에 표시
 *     limit: 지정한 길이만큼 표시
 * }
 * 사용법)
 *     {{ null | string : { post: '년' } }} => null
 *     {{ '2021' | string : { post: '년' } }} => '2021년'
 *     {{ '2021' | string : { replace: '(%s년 리모델링)' } }} => '(2021년 리모델링)'
 *     {{ 25 | string : { replace: '(지상 %s층)' } }} {{ 8 | string : { replace: ' / 지하 %s층' } }} => '지상 25층 / 지하 8층'
 *     {{ 25 | string : { replace: '(지상 %s층)' } }} {{ null | string : { replace: ' / 지하 %s층' } }} => '지상 25층'
 */
@Pipe({ name: 'string' })
export class StringPipe implements PipeTransform {
    transform(value: number | string, options?: { replace: string, pre: string, post: string, limit: number }): string {
        if (value) {
            let result: string = null;
            if (options?.replace) {
                result = options?.replace.replace('%s', ''+ value);
            } else {
                result = ((options?.pre) ? options?.pre : '') + value + ((options?.post) ? options?.post : '');
            }
            
            if (options.limit && result.length > options.limit) {
                result = result.slice(0, options.limit) +'...';
            }
            return result;
        } else {
            return null;
        }
    }
}

typescript, angular

 

숫자 데이터가 0인 경우 -로 표시하기 위해 기존 number 파이프 대신 제작

 

/**
 * 숫자형식 표시
 * 데이터가 0인 경우 - 로 표시
 * options {
 *     digits: 소수점 이하 표시할 자릿수,
 *     unit: 값 뒤에 표시할 단위명,
 *     text: 값이 null 일 때 표시할 텍스트,
 * }
 * 사용법)
 *     {{ 0 | number0 }} => -
 *     {{ null | number0 }} => null
 *     {{ null | number0 : { text: '별도표시' } }} => '별도표시'
 *     {{ 1234.12345 | number0 : { digits: 2, unit: '원' } }} => 1234.12원
 *     {{ 1234.12 | number0 : { replace: '(%s㎡)' } }} => '(1,234.12㎡)'
 */
@Pipe({ name: 'number0' })
export class NumberZero implements PipeTransform {
    transform(value: number | string, options?: { digits: number, unit: string, text: string, replace: string }): string {
        if (value != null) {
            let num = null;

            if (typeof(value) === 'string') {
                num = Number(value);
                if (isNaN(num)) {
                    return null;
                }
            } else {
                num = value;
                if (isNaN(num)) {
                    return null;
                }
            }

            if (num === 0) {
                return '-';
            } else {
                if (options?.replace) {
                	return options?.replace.replace('%s', trunc(num, options?.digits));
                } else {
                	return trunc(num, options?.digits) + ((options?.unit) ? options?.unit : '');
                }
            }
        } else {
            return (options?.text) ? options?.text : null;
        }
    }
}

function trunc(number, digits) {
    const n = number + '';
    const pos = n.lastIndexOf('.');
    if (pos > -1) {
        if (digits == null) {
            digits = n.length - (pos + 1);
        }
        return parseFloat(n.substr(0, pos + digits + 1)).toLocaleString('en', { minimumFractionDigits: digits });
    } else {
        if (digits == null) {
            digits = 0;
        }
        return number.toLocaleString('en', { minimumFractionDigits: digits });
    }
}

Angular 5 file upload using primeng fileupload component
    uploadImage(event, fu: FileUpload) {
        // file.name, file.size, file.type, file.objectURL
        const file: File = event.files[0];
        const reader: FileReader = new FileReader();

        reader.onloadend = (e) => {
            this.image = reader.result as string;  // Base64 문자열 이미지 데이터 저장
            fu.clear();     // 다시 업로드 가능하게 초기화
        };

        if (file) {
            reader.readAsDataURL(file);     // Base64 문자열 변환
        }
    }