티스토리 뷰

FrontEnd/Angular

2018-09-14 개발일지

철철22 2018. 9. 14. 12:10
반응형

어제는 data를 화면에 뿌리는 것까지 성공했다.

이번에 구현을 할것은 버튼 기능이다.


페이지네이션 검색 등 구현해야할 부분은 많은데 그 중에서 우선적으로 구현해야할 부분은 버튼기능인 것 같아

먼저 구현을 한다.


어제 글을 다시 설명하면 현재 컴포넌트의 데이터 전달은 다음과 같으며



내가 구현하고 싶은 기능은 다음과 같다.

하늘색은 사용자 화면단 부분이고

녹색은 data-table 모듈이고

노랑색은 사용자가 만들고자 하는 column을 설정하는 부분이다


그래서

1. 사용자는 모듈에게 row data들을 주고

2. column을 설정하는 부분(directive) 에게는 column 데이터를 주며

3. directive에서 받은 column 데이타를 다시 모듈에게 데아터를 줘

4. 화면단에 표시해준다.



이제 오늘은 이 부분을 해결해야 한다.


버튼 기능을 구현할 때 부모에서 만든 버튼 Method를 실행 할 때 
=> 어떤 Method를 실행할 것인지 directive에 전달하고 button구현은 모듈에서 하는데,
    모듈에서 구현한 button에서 사용자 method를 실행을 시키는 방법을 모르겠다.


일단  메서드 호출을 어떻게 해야할지 고민을 해봤다.


데이터 흐름이 기존 angular 개발할 때처럼 service를 사용하거나 본인의 메서드를 호출하는게 아니라 위의 사진처럼 흐름이 진행되게 할 것이라 방법을 찾기가 어려웠다.



결국 string으로 클레스를 호출하는 Java의 Reflection 방법으로 호출하기로 했다.


여기서 봐야할 부분은 이 두가지다.

(myEvent)='setMethod($event)'
toggle='onClick(age)'
<app-data-table [rows]='this.data' (myEvent)='setMethod($event)'>
  <appDataTableColumn name='index' keyName='id' [width]='50' [widthType]='widthType.ABSOLUTE' [dataType]='dataType.STRING'></appDataTableColumn>
  <appDataTableColumn name='이름' keyName='name' [width]='110' [widthType]='widthType.ABSOLUTE' [dataType]='dataType.STRING'></appDataTableColumn>
  <appDataTableColumn name='성별' keyName='gender' [width]='200' [widthType]='widthType.ABSOLUTE' [dataType]='dataType.STRING'></appDataTableColumn>
  <appDataTableColumn name='나이' keyName='age' [width]='200' [widthType]='widthType.ABSOLUTE' [dataType]='dataType.STRING'></appDataTableColumn>
  <appDataTableColumn name='주소' keyName='address.city' [width]='15' [widthType]='widthType.RELATIVE' [dataType]='dataType.BUTTON' toggle="onClick2(address.city)"></appDataTableColumn>
  <appDataTableColumn name='수정' [width]='15' [widthType]='widthType.RELATIVE' [dataType]='dataType.BUTTON' toggle='onClick(age)'></appDataTableColumn>
</app-data-table>


주황색 화살표 에는 (myEvent) 에 setMethod($event)를 전달할 것이고

빨강색 화살표 에는 toggle='onClick(age)'를 전달할 것이다.

왜냐하면 빨강 화살표는 onClick(age) 라는 string값을 전달해 param으로 age column을 명시하는 것이고

주황 화살표는 directive에서 받아온 string으로 파람 값이 있는지 없는지 확인 사용자 단에 전달할 후 실질적으로 실행시킬 setMethod를 호출시킨다.


설명으로 이해가 안갈 수 있으니 계속 진행 ( 이 전글을 참고하면서 보면 도움이 된다.)



일단 column의 directive에는 다음과 같이 선언한다.

@Input() toggle: EventEmitter<any> = new EventEmitter();


아까 위의 선언의 toggle 을 받는다.

<appDataTableColumn name='수정' [width]='15' [widthType]='widthType.RELATIVE'
[dataType]='dataType.BUTTON' toggle='onClick(age)'></appDataTableColumn>



그리고 data table module에서는 다음과 같이 선언한다.


보면 @Input() 과 @Output을 사용하는데 차이는 


데이터를 전달하기 위해 @Input을 사용해 string 받아주는 것이고

데이터를 받은 것을 전달하기 위해 @Output을 선언한다.


@Output() myEvent: EventEmitter<any> = new EventEmitter();




이제 data moudle을 볼 차례다.

이 글에서 template를 만들었는데 여기서 수정할 부분이 있다.

    <tbody>
      <tr *ngFor="let item of this._rows">
        <ng-container *ngFor="let column of this.columnsConfig">
          <td *ngIf="column.dataType !== dataType.BUTTON; else Btn">
            {{item[column.keyName]}}
          </td>
          <ng-template #Btn>
            <td>
             <!-- <button>{{column.name}}</button> -->
             <button (click)='onClick(item, column)'>{{column.name}}</button>
            </td>
          </ng-template>
        </ng-container>
      </tr>
    </tbody>


component에서는 onclick을 구현해야한다.

    onClick(item, event) {
        const str: string = event.toggle;
        const hasParam = event.toggle.substring(str.indexOf('(') + 1, str.lastIndexOf(')'));
        if (hasParam) {
            const param = str.replace(hasParam, '\'' + this.getProp(item, hasParam).toString() + '\'');
            return this.myEvent.emit(param);
        }
        this.myEvent.emit(event.toggle);
    }
이제 마지막으로 사용자 단에서 만들어 줘야 할 메소드가 있다.
    setMethod(event) {
        try {
            console.log('eval에서 보낼 값 : ' + event);
            new Function(eval('this.' + event))();
        } catch (e) { }
    }

setMethod를 받는 event는 onClick(age) 인데 age가 아니라 실제 데이터의 age key의 value를 받는다.



이제 수정버튼을 눌러 어떻게 나오는지 확인해 보자




age 52의 값이 잘 전달됬다.


하지만 이제  setMethod에서 수정해야할 부분이 있다.

new Function(eval('this.' + event))();


이 부분의 eval을 수정해야한다.

왜냐하면 eval()함수는 자바스크립트 컴파일러에 접근하는 것을 제공해주는데 (Function, setTimeout, SetInterval 도 제공) 모질라의 MDN에서는 eval 함수의 취약점 때문에 사용을 피해야한다고 한다.


그래서 해결방법으로 여러가지를 찾고 있는데 쉽지가 않다.

window[event]()

this[event]()


등등 여러가지를 사용해 봤는데 해결이 안되서 이제 이 부분을 손봐야 한다.




eval()을 대체할 수 있는 방법을 찾았다.

this[event]()의 사용미숙이였다.


new Function(eval('this.' + event))();

이렇게 수정을 하면 된다.

const method = event.substring(0, event.indexOf('('));
const param = event.substring(event.indexOf('(') + 1 ,event.indexOf(')'));
this[method](param);




--------------------------------------------------------------


이 데모 코드는  https://github.com/zlcjfalsvk/custom-gird-module 에서 다운받을 수 있다.



반응형

'FrontEnd > Angular' 카테고리의 다른 글

글모음  (0) 2018.10.18
2018-09-13 개발일지  (0) 2018.09.13
2018-09-12 개발일지  (0) 2018.09.12
2018-09-11 개발일지  (0) 2018.09.11
2018-09-10 개발일지  (0) 2018.09.11
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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 28 29 30 31
글 보관함