관리 메뉴

거니의 velog

(10) 보강 7 본문

대덕인재개발원/대덕인재개발원_final project

(10) 보강 7

Unlimited00 2023. 12. 29. 08:30

https://e-7-e.tistory.com/88

 

ag-grid 간단 사용법

https://www.ag-grid.com/javascript-data-grid/getting-started/ 웹페이지를 만들다 보면 엑셀 모양의 리스트 페이지를 많이 만들게 되고 당연히 리스트를 만들면 페이지 나누기와 검색기능이 들어가야 하고 업

e-7-e.tistory.com


<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="https://cdn.jsdelivr.net/npm/ag-grid-community/dist/ag-grid-community.min.js"></script>
    </head>
    <body>
        <div id="myGrid" style="height: 200px; width:550px;" class="ag-theme-alpine"></div>
        <script>
            const columnDefs = [
              { field: "make"},
              { field: "model", headerName:"모델"},
              { field: "price", headerName:"가격"}
            ];
            
            // 데이타 정의
            const rowData = [
              { make: "Toyota", model: "Celica", price: 35000 },
              { make: "Ford", model: "Mondeo", price: 32000 },
              { make: "Porsche", model: "Boxster", price: 72000 }
            ];
            
            // 설정 옵션: 중요, 위에 정의한 것들이 여기서 통합됨에 주목
            const gridOptions = {
              columnDefs: columnDefs,
              rowData: rowData
            };
            
            // 그리드 셋업, load(이미지, 동영상까지 렌더링시) vs DOMContentLoaded(태그 렌더링시, 이 타이밍이 더 빠름)
            document.addEventListener('DOMContentLoaded', () => {
              const gridDiv = document.querySelector('#myGrid');
              new agGrid.Grid(gridDiv, gridOptions);
            });    
            </script>
    </body>
</html>


<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="https://cdn.jsdelivr.net/npm/ag-grid-community/dist/ag-grid-community.min.js"></script>
    </head>
    <body>
        <div id="myGrid" style="height: 200px; width:550px;" class="ag-theme-alpine"></div>
        <script>
            // sortable:true 은 디폴트로 바뀌었다.
            /*
            const columnDefs = [
            { field: "make",  headerName:"메이커", filter:true, resizable:true},
            { field: "model", headerName:"모델", filter:true, resizable:true},
            { field: "price", headerName:"가격", filter:true, resizable:true}
            ];
            */
            const columnDefs = [
                { field: "make",  headerName:"메이커"},
                { field: "model", headerName:"모델"},
                { field: "price", headerName:"가격"}
            ];
            
            // 데이타 정의
            const rowData = [
              { make: "Toyota", model: "Celica", price: 35000 },
              { make: "Ford", model: "Mondeo", price: 32000 },
              { make: "Porsche", model: "Boxster", price: 72000 }
            ];
            
            // 설정 옵션: 중요, 위에 정의한 것들이 여기서 통합됨에 주목
            const gridOptions = {
                columnDefs: columnDefs,
                rowData: rowData,
                defaultColDef: {
                    sortable:true,
                    filter:true,
                    resizable:true,
                    minWidth:100
                }
            };
            
            // 그리드 셋업, load(이미지, 동영상까지 렌더링시) vs DOMContentLoaded(태그 렌더링시, 이 타이밍이 더 빠름)
            document.addEventListener('DOMContentLoaded', () => {
              const gridDiv = document.querySelector('#myGrid');
              new agGrid.Grid(gridDiv, gridOptions);
            });    
            </script>
    </body>
</html>

순서정렬, 검색 기능과 컬럼 길이 조정도 가능하다.


[
    {
        "name": "태한경",
        "alias": "숨겨진 고민",
        "strong": "다 이해됨",
        "weak": "근거가 없음"
    },
    {
        "name": "공석규",
        "alias": "보면 다 이해",
        "strong": "담배피며 여유찾기",
        "weak": "찾을 여유가 없음"
    },
    {
        "name": "노해건",
        "alias": "수학의 달인",
        "strong": "수학잘함",
        "weak": "산수못함"
    },
    {
        "name": "뢰슬우",
        "alias": "허리 사선",
        "strong": "눈에 안띔",
        "weak": "존재가 안보임"
    },
    {
        "name": "태래은",
        "alias": "일단 직진",
        "strong": "의외로 귀여움",
        "weak": "외모는 전혀 안 귀여움"
    },
    {
        "name": "옥화정",
        "alias": "경로당 느낌?",
        "strong": "나이로 대우받기",
        "weak": "신체나이는?"
    },
    {
        "name": "도중희",
        "alias": "외모는 진지",
        "strong": "눈빛은 남자",
        "weak": "말투는 여성여성"
    },
    {
        "name": "구산아",
        "alias": "알람 그게 뭐얌",
        "strong": "계속 잠",
        "weak": "깨워도 잠"
    },
    {
        "name": "좌하주",
        "alias": "부끄부끄 초딩",
        "strong": "챙겨주고 싶음",
        "weak": "맛집을 모름"
    },
    {
        "name": "나승회",
        "alias": "나름욜씨미 ",
        "strong": "친한척하기",
        "weak": "안 친하고 픔"
    },
    {
        "name": "은진온",
        "alias": "멋짱이",
        "strong": "파란차색깔",
        "weak": "본인은 안 푸름"
    },
    {
        "name": "창승해",
        "alias": "깨달은자",
        "strong": "남의 실수 잘 찾기",
        "weak": "본인 실수는 못 찾음"
    },
    {
        "name": "곡루이스",
        "alias": "배탈",
        "strong": "넘 열심",
        "weak": "취미 없음"
    },
    {
        "name": "상현덕",
        "alias": "오마이걸",
        "strong": "유아 좋아함",
        "weak": "본인 나이는 어쩔"
    },
    {
        "name": "교근찬",
        "alias": "술쎄보임",
        "strong": "좋은마우스",
        "weak": "힘없음"
    },
    {
        "name": "연건한",
        "alias": "그저 웃지요",
        "strong": "답변은 웃음으로",
        "weak": "입이 할일이 없음"
    },
    {
        "name": "홍길동",
        "alias": "전공자",
        "strong": "서류상 전공자",
        "weak": "서류빼면 비전공자"
    },
    {
        "name": "김방구",
        "alias": "엄마",
        "strong": "노력 산더미",
        "weak": "결과는 티끌"
    },
    {
        "name": "김채현",
        "alias": "비밀의 숲",
        "strong": "잘 감춤",
        "weak": "보여주면서 감춤"
    }
]

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ag-Grid Basic Example</title>
<style>
    #wrapper {
        width:650px;
        height:500px;
        margin:50px auto;
        text-align: center;
    }
    #myGrid {
        height: 100%;
    }
    /* 헤더 텍스트 가운데 정렬 위함 */
    .centered {
        .ag-header-cell-label {
        justify-content: center !important;
    }
}
</style>
<script src="https://cdn.jsdelivr.net/npm/ag-grid-community/dist/ag-grid-community.min.js"></script>
</head>
<body>
<div id="wrapper">
    <h1>AG-Grid 꽤 잘 만들었어용</h1>
    <div id="myGrid" class="ag-theme-alpine">
    </div>
    <button onclick="fExp()">내보내깅</button>
</div>
<script>
const columnDefs = [
  { field: "name",  headerName:"이름", sortable:true},
  { field: "alias", headerName:"별명", sortable:true, cellStyle: {textAlign: "left"}},
  { field: "strong", headerName:"장점", cellStyle: {textAlign: "left"}},
  { field: "weak", headerName:"단점", cellStyle: {textAlign: "left"}},
  { field: "birth", headerName:"생일", cellRenderer:MyComp} // 생일은 날짱!
];

// 일단 빈 데이터 설정(초기값), 설정 안하면 주구창창 로딩중 메세지
const rowData = [];  

// 설정 옵션: 중요, 위에 정의한 것들이 여기서 통합됨에 주목
const gridOptions = {
  columnDefs: columnDefs,
  rowData: rowData,
  defaultColDef: {
    flex:1,       // 자동으로 같은 사이즈롱
    filter:true,
    resizable:true,
    minWidth:100,
    headerClass: "centered"

  },

  // 페이지 설정
  pagination:true,
  //paginationAutoPageSize:true,
  paginationPageSize:5,    // 같이 설정하니 위에 꺼 우선순위

  // 다양한 이벤트가 제공되지만, 그 중 많이 쓰게 되는 것
  onCellClicked: params => {
    console.log('cell was clicked',params);
    //alert("클릭하신 값은: " + params.value); //요게 있음 뭔가? 방해됨
  }
};

function getData(){
    var xhr = new XMLHttpRequest();
    xhr.open("get","dummyData.json",true);
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
            // 데이타 구조 억지 땜빵!
            let rslt = JSON.parse(xhr.responseText);
            // 그냥 생일 랜덤하게 넣깅
            for(let i=0; i< rslt.length; i++){
                rslt[i].birth = ranDate();
            }

            gridOptions.api.setRowData(rslt); // 중요!, 외우란 말은 아님
        }
    }
    xhr.send();
}

// csv 내보내기, 별로 안 중요, 그냥 이대로 설정하고 값만 고치면 됨
function fExp(){
    var v_params = {
        suppressQuotes: "true",                 // none, true
        columnSeparator: "   ",                 // default값이 ,
        customHeader: "이름 별명 장점 단점",    // 헤더명 추가 출력
        customFooter: "이거슨 푸터"             // 데이타 아래에 footer추가
    };
    gridOptions.api.exportDataAsCsv(v_params);
}

// 그리드 셋업
document.addEventListener('DOMContentLoaded', () => {
  const gridDiv = document.querySelector('#myGrid');
  new agGrid.Grid(gridDiv, gridOptions);
  getData();  // 데이터 불러오깅
}); 


function MyComp() {
    return this;
}

// AG-GRID 문서에 나오는 커스텀 Cell Renderer
MyComp.prototype.init = function(params) {
    this.eGui = document.createElement('div');
    this.eGui.innerHTML = `
    <input type="date" value="" class="myCal" style="border:0px;width:0px"> 
    <span class="mySpan">${params.value}</span> 
    `;
    
    this.myCal = this.eGui.querySelector('.myCal')
    this.mySpan = this.eGui.querySelector('.mySpan')
    this.mySpan.onclick = () => {
        this.myCal.showPicker();
    }
    this.myCal.onchange = ()=> {
        console.log("check",this.myCal.value);
        this.mySpan.innerHTML = this.myCal.value;
    }
}
MyComp.prototype.getGui=function(){
    console.log("check1");
    return this.eGui;
}
MyComp.prototype.refresh=function(){
    console.log("check2");
    return true;
}
MyComp.prototype.destroy=function(){
    console.log("check3");
} 
function ranDate(){
    let now = new Date();
    now.setDate(now.getDate() - Math.floor(Math.random()*90));
    
    let rYear = now.getFullYear();
    
    let rMonth = now.getMonth() + 1;
    if(rMonth < 10) rMonth = "0" + rMonth;
    
    let rDate = now.getDate();
    if(rDate < 10) rDate = "0" + rDate;
    
    return `${rYear}-${rMonth}-${rDate}`;
}

</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ag-Grid Basic Example</title>
<style>
    #wrapper {
        width:650px;
        height:500px;
        margin:50px auto;
        text-align: center;
    }
    #myGrid {
        height: 100%;
    }
    /* 헤더 텍스트 가운데 정렬 위함 */
    .centered {
        .ag-header-cell-label {
        justify-content: center !important;
    }
}
</style>
<script src="https://cdn.jsdelivr.net/npm/ag-grid-community/dist/ag-grid-community.min.js"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/ag-grid-enterprise/dist/ag-grid-enterprise.min.js"></script> -->
</head>
<body>
<div id="wrapper">
    <h1>AG-Grid 꽤 잘 만들었어용</h1>
    <div id="myGrid" class="ag-theme-alpine">
    </div>
    <button onclick="fExp()">내보내깅</button>
</div>
<script>
const columnDefs = [
  { field: "name",  headerName:"이름", sortable:true},
  { field: "alias", headerName:"별명", sortable:true, cellStyle: {textAlign: "left"}},
  { field: "strong", headerName:"장점", cellStyle: {textAlign: "left"}},
  { field: "weak", headerName:"단점", cellStyle: {textAlign: "left"}},
  { field: "birth", headerName:"생일", cellRenderer:MyComp} // 생일은 날짱!
];

// 일단 빈 데이터 설정(초기값), 설정 안하면 주구창창 로딩중 메세지
const rowData = [];  

// 설정 옵션: 중요, 위에 정의한 것들이 여기서 통합됨에 주목
const gridOptions = {
  columnDefs: columnDefs,
  rowData: rowData,
  defaultColDef: {
    flex:1,       // 자동으로 같은 사이즈롱
    filter:true,
    resizable:true,
    minWidth:100,
    headerClass: "centered"

  },

  // 페이지 설정
  pagination:true,
  //paginationAutoPageSize:true,
  paginationPageSize:5,    // 같이 설정하니 위에 꺼 우선순위

  // 다양한 이벤트가 제공되지만, 그 중 많이 쓰게 되는 것
  onCellClicked: params => {
    console.log('cell was clicked',params);
    //alert("클릭하신 값은: " + params.value); //요게 있음 뭔가? 방해됨
  }
};

function getData(){
    var xhr = new XMLHttpRequest();
    xhr.open("get","dummyData.json",true);
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
            // 데이타 구조 억지 땜빵!
            let rslt = JSON.parse(xhr.responseText);
            // 그냥 생일 랜덤하게 넣깅
            for(let i=0; i< rslt.length; i++){
                rslt[i].birth = ranDate();
            }

            //gridOptions.api.setRowData(rslt); // 중요!, 외우란 말은 아님
            gridOptions.api.updateGridOptions({ rowData: rslt });
        }
    }
    xhr.send();
}

// csv 내보내기, 별로 안 중요, 그냥 이대로 설정하고 값만 고치면 됨
function fExp(){
    var v_params = {
        suppressQuotes: "true",                 // none, true
        columnSeparator: "   ",                 // default값이 ,
        customHeader: "이름 별명 장점 단점",    // 헤더명 추가 출력
        customFooter: "이거슨 푸터"             // 데이타 아래에 footer추가
    };
    gridOptions.api.exportDataAsCsv(v_params);
}

// 그리드 셋업
document.addEventListener('DOMContentLoaded', () => {
  const gridDiv = document.querySelector('#myGrid');
  new agGrid.Grid(gridDiv, gridOptions);
  getData();  // 데이터 불러오깅
}); 


function MyComp() {
    return this;
}

// AG-GRID 문서에 나오는 커스텀 Cell Renderer
MyComp.prototype.init = function(params) {
    this.eGui = document.createElement('div');
    this.eGui.innerHTML = `
    <input type="date" value="" class="myCal" style="border:0px;width:0px"> 
    <span class="mySpan">${params.value}</span> 
    `;
    
    this.myCal = this.eGui.querySelector('.myCal')
    this.mySpan = this.eGui.querySelector('.mySpan')
    this.mySpan.onclick = () => {
        this.myCal.showPicker();
    }
    this.myCal.onchange = ()=> {
        console.log("check",this.myCal.value);
        this.mySpan.innerHTML = this.myCal.value;
    }
}
MyComp.prototype.getGui=function(){
    console.log("check1");
    return this.eGui;
}
MyComp.prototype.refresh=function(){
    console.log("check2");
    return true;
}
MyComp.prototype.destroy=function(){
    console.log("check3");
} 
function ranDate(){
    let now = new Date();
    now.setDate(now.getDate() - Math.floor(Math.random()*90));
    
    let rYear = now.getFullYear();
    
    let rMonth = now.getMonth() + 1;
    if(rMonth < 10) rMonth = "0" + rMonth;
    
    let rDate = now.getDate();
    if(rDate < 10) rDate = "0" + rDate;
    
    return `${rYear}-${rMonth}-${rDate}`;
}

</script>
</body>
</html>

enterprise인 경우..


* cross origin? -> Ajax의 마지막은 cross origin을 극복하는 것.

- origin(출처) : 프로토콜 + 도메인명 + 포트번호
  http://(=>프로토콜, 약속이라고 하면 된다.)localhost(도메인명/서버명):80(포트번호)
  https://localhost:80
  https://127.0.0.1:80
  https:localhost:8080

- 이 origin 중 하나라도 다르면 cross origin 이라고 부른다.

- same-origin 정책 위반. daum 서버에서 온 요청은 daum 안에서만 가능. naver로 요청하면 error가 발생. 익명성을 거부. 서비스를 제공하는 서버라는 분명한 정체성을 증명해야 함.

- 리턴된 결과를 res 변수에 받음. 내 마음대로 조작하고 브라우저에 뿌릴 수 있다는 말이다. 피싱 사이트 이외의 비슷한 사이트를 순식간에 제작할 위험성이 있다.

- 이를 어떻게 해결해야 하는가? 내가 네이버의 어떤 결과 페이지가 필요하다면 직접 접근 방식은 불가하고, 다음에서 다음 서버로 요청하고 다음서버에서 네이버로 요청해 다음 서버로 받고 내 페이지로 받는 우회 요청으로 처리해야 한다.

'대덕인재개발원 > 대덕인재개발원_final project' 카테고리의 다른 글

(12) 보강 8  (0) 2024.01.02
(11) 토요일 수업 2  (0) 2023.12.30
(9) 보강 6  (0) 2023.12.28
(8) 보강 5  (0) 2023.12.27
(7) 보강 4  (0) 2023.12.26