Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 개발자
- 그릭요거트
- 파티룸
- mysql
- 서울파티룸
- 코딩
- 휴식
- 부천공간대여
- 옥길그릭요거트
- 스페이스우일
- 해외여행
- 스컬킹점수계산
- 부천파티룸
- 스컬킹점수
- MBTI
- 옥길동파티룸
- 존경하는위인
- 옥길파티룸
- 웹개발
- 취미
- 옥길요거트
- 구로파티룸
- 옥길동요거트
- 보드게임점수
- 가장존경하는인물
- 스컬킹
- 광명파티룸
- 착한코딩
- 일
- 보드게임점수계산
Archives
- Today
- Total
SIMPLE & UNIQUE
3회차_2강 : 수정페이지를 구현한다. (text, 이미지, 파일) 본문
탈잉 강의 자료/react.js(프론트) + node.js(백앤드) 개발에서 배포까지
3회차_2강 : 수정페이지를 구현한다. (text, 이미지, 파일)
착한코딩 2020. 1. 16. 01:083_2 목표 : 이미 등록된 데이터를 수정페이지 form에 노출시키고, 수정기능을 등록페이지 로직과 동일하게 구현한다.
1. 등록페이지 react 파일에 수정 기능을 추가한다.
AdminSoftwareView.js 파일에 아래 소스를 붙여넣는다.
state에 수정에 필요한 변수들을 선언했고, node api를 호출해 기존에 저장한 데이터를 호출해 화면에 노출시키는 스크립트 코드가 추가됐다.
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
import axios from "axios";
import $ from 'jquery';
class SoftwareView extends Component {
constructor(props) {
super(props);
this.state = {
responseSwtoolInfo: '',//swtool 정보 response 변수
append_SwtoolInfo: '', //swtool 정보 append 변수
before_swtcode: props.match.params.swtcode, //swtool 정보 swtool 코드
swtcode: '', //swtool 저장 swtool 코드
swt_toolname: '', //swtool 정보 sw툴 명
swt_demo_site: '',//swtool 정보 데모사이트
swt_github_url: '',//swtool 정보 깃허브 주소
swt_comments: '',//swtool 정보 설명
swt_function: '',//swtool 정보 기능
//파일, 이미지 업로드
file: '',//메인 이미지 미리보기용 path
file2: '',//라벨 이미지 미리보기용 path
fileName: '',//메인 이미지명
fileName2: '',//라벨 이미지명
menualName: '',//메뉴얼명
selectedFile: null, //업로드 대상 파일
}
}
componentDidMount () {
// SW Tool 정보 호출
this.callSwToolInfoApi()
if(this.state.before_swtcode == 'register'){
$('.modifyclass').hide()
}else{
$('.saveclass').hide()
}
}
//업로드할 파일 세팅
handleFileInput(type, e){
var id = e.target.id
if(type =='file'){
$('#imagefile').val(e.target.files[0].name)
}else if(type =='file2'){
$('#imagefile2').val(e.target.files[0].name)
}else if(type =='manual'){
$('#manualfile').val(e.target.files[0].name)
}
this.setState({
selectedFile : e.target.files[0],
})
if(type =='manual'){
setTimeout(function() {
this.handlePostMenual(type, id ,e)
}.bind(this),1
);
}else{
setTimeout(function() {
this.handlePostImage(type, id ,e)
}.bind(this),1
);
}
}
//메뉴얼 업로드
handlePostMenual(type, id, e){
const formData = new FormData();
formData.append('file', this.state.selectedFile);
return axios.post("/api/upload?type=uploads/swmanual/", formData).then(res => {
try {
this.state.menualName = res.data.filename
$('#upload_menual').prepend('<input id="is_MenualName" type="hidden" name="is_MenualName" value="'+this.state.menualName+'"}/>')
} catch (error) {
alert('작업중 오류가 발생하였습니다.', error, 'error', '닫기')
}
}).catch(error => {
alert('작업중 오류가 발생하였습니다.', error, 'error', '닫기')
})
}
//이미지 업로드
handlePostImage(type, id, e){
const formData = new FormData();
formData.append('file', this.state.selectedFile);
return axios.post("/api/upload?type=uploads/image/", formData).then(res => {
try {
setTimeout(function() {
if(type =='file'){
this.state.file = '/image/'+res.data.filename
this.state.fileName = res.data.filename
$('#uploadimg').show()
$('#is_MainImg').remove()
$('#uploadimg').remove()
$('#upload_img').prepend('<img id="uploadimg" src="'+this.state.file+'"/>')
$('#upload_img').prepend('<input id="is_MainImg" type="hidden" name="is_MainImg" value="'+this.state.fileName+'"}/>')
}else if(type =='file2'){
this.state.file2 = '/image/'+res.data.filename
this.state.fileName2 = res.data.filename
$('#uploadimg2').show()
$('#is_LabelImg').remove()
$('#uploadimg2').remove()
$('#upload_img2').prepend('<img id="uploadimg2" src="'+this.state.file2+'"/>')
$('#upload_img2').prepend('<input id="is_LabelImg" type="hidden" name="is_LabelImg" value="'+this.state.fileName2+'"}/>')
}
}.bind(this),1000
);
} catch (error) {
alert('작업중 오류가 발생하였습니다.')
}
}).catch(error => {
alert('작업중 오류가 발생하였습니다.')
})
}
// SW Tool 정보 호출
callSwToolInfoApi = async () => {
//SW Tool List 호출
axios.post('/api/Swtool?type=info', {
is_Swtcode: this.state.before_swtcode,
})
.then( response => {
try {
this.setState({ responseSwtoolInfo: response });
this.setState({ append_SwtoolInfo: this.SwToolInfoAppend() });
$('#is_Swt_toolname').val(this.state.swt_toolname)
$('#is_Swt_demo_site').val(this.state.swt_demo_site)
$('#is_Giturl').val(this.state.swt_github_url)
$('#is_Comments').val(this.state.swt_comments)
$('#is_Swt_function').val(this.state.swt_function)
$('#upload_img').prepend('<img id="uploadimg" src="'+this.state.file+'"/>')
$('#upload_img').prepend('<input id="is_MainImg" type="hidden" name="is_MainImg" value="'+this.state.fileName+'"}/>')
$('#upload_img2').prepend('<img id="uploadimg2" src="'+this.state.file2+'"/>')
$('#upload_img2').prepend('<input id="is_LabelImg" type="hidden" name="is_LabelImg" value="'+this.state.fileName2+'"}/>')
$('#imagefile').val(this.state.fileName)
$('#imagefile2').val(this.state.fileName2)
$('#manualfile').val(this.state.menualName)
if($('#uploadimg').attr('src').indexOf("null") > -1){
$('#uploadimg').hide()
}
if($('#uploadimg2').attr('src').indexOf("null") > -1){
$('#uploadimg2').hide()
}
} catch (error) {
alert('작업중 오류가 발생하였습니다.')
}
})
.catch( error => {alert('작업중 오류가 발생하였습니다.');return false;} );
}
// SW Tool 정보 append
SwToolInfoAppend = () => {
let result = []
var SwToolInfo = this.state.responseSwtoolInfo.data
if(this.state.before_swtcode != 'register'){
var data = SwToolInfo.json[0]
this.state.swt_toolname = data.swt_toolname
this.state.swt_demo_site = data.swt_demo_site
this.state.swt_github_url = data.swt_github_url
this.state.swt_comments = data.swt_comments
this.state.swt_function = data.swt_function
this.state.file = '/image/'+data.swt_big_imgpath
this.state.fileName = data.swt_big_imgpath
$('#imagefile').val(data.swt_big_imgpath)
this.state.file2 = '/image/'+data.swt_imagepath
this.state.fileName2 = data.swt_imagepath
$('#imagefile2').val(data.swt_imagepath)
this.state.menualName = data.swt_manual_path
}
result.push(
<table class="table_ty1">
<tr>
<th>
<label for="is_Swt_toolname">툴 이름<span class="red">(*)</span></label>
</th>
<td>
<input type="text" name="is_Swt_toolname" id="is_Swt_toolname" class="" />
</td>
</tr>
<tr>
<th>
<label for="is_Swt_demo_site">데모 URL<span class="red">(*)</span></label>
</th>
<td>
<input type="text" name="is_Swt_demo_site" id="is_Swt_demo_site" class="" />
</td>
</tr>
<tr>
<th>
<label for="is_Giturl">Github URL<span class="red">(*)</span></label>
</th>
<td>
<input type="text" name="is_Giturl" id="is_Giturl" class="" />
</td>
</tr>
<tr>
<th>
<label for="is_Comments">설명<span class="red">(*)</span></label>
</th>
<td>
<textarea name="is_Comments" id="is_Comments" rows="" cols=""></textarea>
</td>
</tr>
<tr class="div_tb_tr fileb">
<th>
메뉴얼 파일 #1
</th>
<td class="fileBox fileBox_w1">
<label for="uploadBtn1" class="btn_file">파일선택</label>
<input type="text" id="manualfile" class="fileName fileName1" readonly="readonly" placeholder="선택된 파일 없음"/>
<input type="file" id="uploadBtn1" class="uploadBtn uploadBtn1" onChange={e => this.handleFileInput('manual',e)}/>
<div id="upload_menual">
</div>
</td>
</tr>
<tr>
<th>
메인 이미지
</th>
<td className="fileBox fileBox1">
<label htmlFor='imageSelect' className="btn_file">파일선택</label>
<input type="text" id="imagefile" className="fileName fileName1" readOnly="readonly" placeholder="선택된 파일 없음"/>
<input type="file" id="imageSelect" className="uploadBtn uploadBtn1" onChange={e => this.handleFileInput('file',e)}/>
<div id="upload_img">
</div>
</td>
</tr>
<tr>
<th>
라벨 이미지
</th>
<td className="fileBox fileBox2">
<label htmlFor='imageSelect2' className="btn_file">파일선택</label>
<input type="text" id="imagefile2" className="fileName fileName1" readOnly="readonly" placeholder="선택된 파일 없음"/>
<input type="file" id="imageSelect2" className="uploadBtn uploadBtn1" onChange={e => this.handleFileInput('file2',e)}/>
<div id="upload_img2">
</div>
</td>
</tr>
<tr>
<th>
<label for="is_Swt_function">상세 기능<span class="red">(*)</span></label>
</th>
<td>
<textarea name="is_Swt_function" id="is_Swt_function" rows="" cols=""></textarea>
</td>
</tr>
</table>
)
return result
}
// 저장 버튼 클릭시 validate check
submitClick = async (type, e) => {
this.Swt_toolname_checker = $('#is_Swt_toolname').val();
this.Swt_demo_site_checker = $('#is_Swt_demo_site').val();
this.Giturl_checker = $('#is_Giturl').val();
this.Comments_checker = $('#is_Comments').val();
this.Swt_function_checker = $('#is_Swt_function').val();
this.fnValidate = (e) => {
// ## Swt_toolname check start
if(this.Swt_toolname_checker === '') {
$('#is_Swt_toolname').addClass('border_validate_err');
alert('툴 이름을 다시 확인해주세요.')
return false;
}
$('#is_Swt_toolname').removeClass('border_validate_err');
// ## Swt_demo_site check start
if(this.Swt_demo_site_checker === '') {
$('#is_Swt_demo_site').addClass('border_validate_err');
alert('데모 URL을 다시 확인해주세요.')
return false;
}
$('#is_Swt_demo_site').removeClass('border_validate_err');
// ## Giturl check start
if(this.Giturl_checker === '') {
$('#is_Giturl').addClass('border_validate_err');
alert('Github URL을 다시 확인해주세요.')
return false;
}
$('#is_Giturl').removeClass('border_validate_err');
// ## Comments check start
if(this.Comments_checker === '') {
$('#is_Comments').addClass('border_validate_err');
alert('설명을 다시 확인해주세요.')
return false;
}
$('#is_Comments').removeClass('border_validate_err');
// ## Swt_function check start
if(this.Swt_function_checker === '') {
$('#is_Swt_function').addClass('border_validate_err');
alert('상세기능을 다시 확인해주세요.')
return false;
}
$('#is_Swt_function').removeClass('border_validate_err');
var date = new Date()
var y_str = date.getFullYear().toString();
var month = date.getMonth()+1
var m_str = month.toString();
var day = date.getDate()
var d_str = day.toString();
var hour = date.getHours()
var min = date.getMinutes()
var sec = date.getSeconds()
// 프로젝트 코드생성
this.state.swtcode = 'USW'+y_str+m_str+d_str+hour+min+sec
$('#is_Swtcode').val(this.state.swtcode)
return true;
}
//유효성 체크
if(this.fnValidate()){
//software Tools 저장
//form type To Json
var jsonstr = $("form[name='frm']").serialize();
//특수문자 깨짐 해결
jsonstr = decodeURIComponent(jsonstr);
var Json_form = JSON.stringify(jsonstr).replace(/\"/gi,'')
Json_form = "{\"" +Json_form.replace(/\&/g,'\",\"').replace(/=/gi,'\":"')+"\"}";
try {
const response = await fetch('/api/Swtool?type='+type, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
//한글 디코딩
body: Json_form,
});
const body = await response.text();
if(body == "succ"){
if(type == 'save'){
alert('Software Tools 등록이 완료되었습니다.')
}else if(type == "modify"){
alert('Software Tools 수정이 완료되었습니다.')
}
// 저장 후 리스트페이지로 이동
setTimeout(function() {
// datasource 정보 호출
window.location.href = 'http://localhost:3000/AdminSoftwareList';
}.bind(this),1500
);
}else{
alert('작업중 오류가 발생하였습니다.')
}
} catch (error) {
alert('작업중 오류가 발생하였습니다.')
}
}//fnValidate end
};
render () {
return (
<section class="sub_wrap">
<article class="s_cnt mp_pro_li ct1">
<div class="li_top">
<h2 class="s_tit1">Software Tools 등록/수정</h2>
</div>
<div class="bo_w re1_wrap re1_wrap_writer">
<form name="frm" id="frm" action="" onsubmit="" method="post" >
<input id="is_Email" type="hidden" name="is_Email" value={this.state.admin_userid} />
<input id="is_Swtcode" type="hidden" name="is_Swtcode" value={this.state.swtcode} />
<input id="is_beforeSwtcode" type="hidden" name="is_beforeSwtcode" value={this.state.before_swtcode} />
<article class="res_w">
<p class="ment" style={{"text-align": "right"}}>
<span class="red">(*)</span>표시는 필수입력사항 입니다.
</p>
<div class="tb_outline">
{this.state.append_SwtoolInfo}
<div class="btn_confirm mt20" style={{"margin-bottom": "44px"}}>
<Link to={'/AdminSoftwareList'} className="bt_ty bt_ty1 cancel_ty1">취소</Link>
<a href="javascript:" className="bt_ty bt_ty2 submit_ty1 saveclass" onClick={(e) => this.submitClick('save', e)}>저장</a>
<a href="javascript:" className="bt_ty bt_ty2 submit_ty1 modifyclass" onClick={(e) => this.submitClick('modify', e)}>수정</a>
</div>
</div>
</article>
</form>
</div>
</article>
</section>
);
}
}
export default SoftwareView;
2. node 경로에 등록된 데이터를 불러오고, 새로운 데이터로 수정하는 함수와 쿼리를 작성한다.
SwtoolModule.js 파일을 아래와 같이 수정한다.
tool 상세페이지에 노출한 데이터를 호출하는 mapper를 호출하는 로직(m_typ=info)과
새로운 데이터를 수정하는 로직(m_typ=modify)을 추가했다.
var express = require('express');
var router = express.Router();
const bodyParser = require('body-parser');
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: true }));
router.post('/', (req, res, next) => {
var m_typ = req.query.type;
if(m_typ == 'list'){
//Swtool 리스트 조회
try {
// Mysql Api 모듈(CRUD)
var dbconnect_Module = require('./dbconnect_Module');
//Mysql 쿼리 호출정보 입력
req.body.mapper = 'SwToolsMapper';//mybatis xml 파일명
req.body.crud = 'select';//select, insert, update, delete 중에 입력
req.body.mapper_id = 'selectSwToolsList';
router.use('/', dbconnect_Module);
next('route')
} catch (error) {
console.log("Module > dbconnect error : "+ error);
}
}else if(m_typ == 'save'){
//Swtool 관리자 저장
try {
// Mysql Api 모듈(CRUD)
var dbconnect_Module = require('./dbconnect_Module');
//Mysql 쿼리 호출정보 입력
req.body.mapper = 'SwToolsMapper';//mybatis xml 파일명
req.body.crud = 'insert';//select, insert, update, delete 중에 입력
req.body.mapper_id = 'insertSwToolsInfo';
router.use('/', dbconnect_Module);
next('route')
} catch (error) {
console.log("Module > dbconnect error : "+ error);
}
}else if(m_typ == 'info'){
//Swtool 정보 조회
try {
// Mysql Api 모듈(CRUD)
var dbconnect_Module = require('./dbconnect_Module');
//Mysql 쿼리 호출정보 입력
req.body.mapper = 'SwToolsMapper';//mybatis xml 파일명
req.body.crud = 'select';//select, insert, update, delete 중에 입력
req.body.mapper_id = 'selectSwToolsInfo';
router.use('/', dbconnect_Module);
next('route')
} catch (error) {
console.log("Module > dbconnect error : "+ error);
}
}else if(m_typ == 'modify'){
//Swtool 관리자 수정
try {
// Mysql Api 모듈(CRUD)
var dbconnect_Module = require('./dbconnect_Module');
//Mysql 쿼리 호출정보 입력
req.body.mapper = 'SwToolsMapper';//mybatis xml 파일명
req.body.crud = 'update';//select, insert, update, delete 중에 입력
req.body.mapper_id = 'updateSwToolsInfo';
router.use('/', dbconnect_Module);
next('route')
} catch (error) {
console.log("Module > dbconnect error : "+ error);
}
}
});
module.exports = router;
SwToolsMapper.xml 파일을 아래와 같이 수정한다. tool 리스트가 아닌 1개의 데이터만 가져오는 select 쿼리와
새로운 데이를 update 해주는 쿼리가 추가됐다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="SwToolsMapper">
<select id="selectSwToolsList">
SELECT
swt_code
, swt_toolname
, swt_function
, swt_imagepath
, swt_big_imgpath
, swt_comments
, swt_demo_site
, swt_manual_path
, swt_github_url
, reg_date
FROM rtrod.rtrod_swtool
ORDER BY update_date DESC
<if test="startRow != null && startRow != ''">
limit ${startRow}, ${endRow}
</if>
</select>
<insert id="insertSwToolsInfo">
INSERT INTO rtrod.rtrod_swtool
(
swt_code
, swt_toolname
, swt_function
, swt_comments
, swt_demo_site
, swt_github_url
<if test="is_LabelImg != null && is_LabelImg != ''">
, swt_imagepath
</if>
<if test="is_MainImg != null && is_MainImg != ''">
, swt_big_imgpath
</if>
<if test="is_MenualName != null && is_MenualName != ''">
, swt_manual_path
</if>
, reg_date
, reg_user
, update_date
, update_user
)
VALUES (
#{is_Swtcode}
, #{is_Swt_toolname}
, #{is_Swt_function}
, #{is_Comments}
, #{is_Swt_demo_site}
, #{is_Giturl}
<if test="is_LabelImg != null && is_LabelImg != ''">
, #{is_LabelImg}
</if>
<if test="is_MainImg != null && is_MainImg != ''">
, #{is_MainImg}
</if>
<if test="is_MenualName != null && is_MenualName != ''">
, #{is_MenualName}
</if>
, DATE_FORMAT(now(), '%Y%m%d%H%i%s')
, #{is_Email}
, DATE_FORMAT(now(), '%Y%m%d%H%i%s')
, #{is_Email}
)
</insert>
<select id="selectSwToolsInfo">
SELECT
swt_code
, swt_toolname
, swt_function
, swt_imagepath
, swt_big_imgpath
, swt_comments
, swt_demo_site
, swt_manual_path
, swt_github_url
, reg_date
FROM rtrod.rtrod_swtool
<if test="is_Swtcode != null && is_Swtcode != ''">
WHERE swt_code = #{is_Swtcode}
</if>
</select>
<update id="updateSwToolsInfo">
UPDATE rtrod.rtrod_swtool
SET
swt_toolname = #{is_Swt_toolname}
, swt_function = #{is_Swt_function}
, swt_comments = #{is_Comments}
, swt_demo_site = #{is_Swt_demo_site}
, swt_github_url = #{is_Giturl}
<if test="is_LabelImg != null && is_LabelImg != ''">
, swt_imagepath = #{is_LabelImg}
</if>
<if test="is_MainImg != null && is_MainImg != ''">
, swt_big_imgpath = #{is_MainImg}
</if>
<if test="is_MenualName != null && is_MenualName != ''">
, swt_manual_path = #{is_MenualName}
</if>
, update_date = DATE_FORMAT(now(), '%Y%m%d%H%i%s')
, update_user = #{is_Email}
WHERE swt_code = #{is_beforeSwtcode}
</update>
</mapper>
3. 수정이 정상적으로 동작하는지 확인한다.
상세페이지에서 데이터 수정 후, 리스트로 돌아와 다시 상세페이지로 진입하면 수정된 데이터를 확인할 수 있다.
'탈잉 강의 자료 > react.js(프론트) + node.js(백앤드) 개발에서 배포까지' 카테고리의 다른 글
4회차_1강 : EC2 서버 인스턴스를 생성하고, SFTP, SSH 을 사용할 수 있게 세팅한다. (0) | 2020.01.22 |
---|---|
3회차_3강 : ALERT 디자인을 수정하고, 삭제기능을 구현한다. Source tree를 사용해 git에 소스를 업로드한다. (0) | 2020.01.16 |
3회차_1강 : 등록페이지를 구현한다. (text, 이미지, 파일) (2) | 2020.01.16 |
2회차_2강 : AWS 가입, RDS mysql 인스턴스를 구동하고 스키마와 테이블을 생성한다. (0) | 2020.01.07 |
2회차_1강 : AWS RDS mysql 서버 연결 후, 데이터를 웹으로 가져온다. (0) | 2020.01.05 |
Comments