728x90
반응형
입력 글자 수 제한을 사용자가 알기 쉽게 화면에 동적 입력 글자 수 표현
*자세한 설명 생략
▷ Computed 란?
- template의 data 표현을 간결하게 하는 속성
- 가독성 ↑ 유지보수 ↑
*한눈에 알아보기
- 사용하기 전 코드
<h6 v-if="(inMsg.replaceAll('\n', '').length <= MAX)">
( {{ inMsg.replaceAll('\n', '').length }} 자 / 최대 {{ MAX }} 자
</h6>
<h6 class="maxInfo" v-else>
( {{ inMsg.replaceAll('\n', '').length }} 자 / 최대 {{ MAX }} 자 )
</h6>
- 사용 후 코드
<h6 v-if="(inMsgSize <= MAX)">
( {{ inMsgSize }} 자 / 최대 {{ MAX }} 자 )
</h6>
<h6 class="maxInfo" v-else>
( {{ inMsgSize }} 자 / 최대 {{ MAX }} 자 )
</h6>
▷ 프로젝트 전체 구조
▷ 기초 예제 - 입력 글자 수 표시
*전체 코드
*주석 이외 설명 생략
- index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
- Cmp.css
.MsgSendCmp {
font-family: 'Spoqa Han Sans';
margin-top: 10%;
text-align: center;
}
.maxCheckDiv {
margin-left: 200px;
}
.maxInfo {
color: red;
}
.messageDiv {
white-space: pre-wrap;
text-align: left;
margin-left: 5%;
margin-right: 5%;
}
.toast {
width: auto;
}
.smallButton {
margin-left: 15px;
height: 3px;
}
- main.js
/** Vue */
import { createApp } from 'vue'
import App from './App.vue'
/** PrimeVue */
import PrimeVue from 'primevue/config'
import 'primevue/resources/themes/lara-light-teal/theme.css'
import ToastService from 'primevue/toastservice'
createApp(App)
/** 라이브러리 사용 등록 */
.use(PrimeVue)
.use(ToastService)
/** 연결 */
.mount('#app')
- App.vue
<style>
@import url('@/assets/css/Cmp.css');
</style>
<template>
<div>
<MsgSendCmp />
</div>
</template>
<script>
import MsgSendCmp from '@/components/MsgSendCmp.vue'
export default {
name: 'App',
components: {
MsgSendCmp
}
}
</script>
- AxiosModule.js
import Axios from "axios"
const API_SERVER = "http://IP:PORT
const API_LIST = {
"CMS-SEND-MSG": "/support/cmd",
}
function sendPost(API_URI, REQ_DATA) {
return Axios
.post(API_SERVER + API_URI, REQ_DATA)
.then((res) => {
return res.status
})
.catch((res) => {
alert("잠시 후 다시 시도해주세요.")
return res.status
})
}
export {
API_LIST,
sendPost
}
- CmmUtile.js
/**
* Toast 설정
*
* @param {*} toast
* @param {*} code
*/
function setToast(toast, code) {
const S = "success"
const E = "error"
const L = 1500
if ("0000" == code) { toast.add({ detail: 'Message has been Send.', severity: S, summary: S, life: L }) }
if ("0001" == code) { toast.add({ detail: 'Message has been Deleted.', severity: S, summary: S, life: L }) }
if ("0002" == code) { toast.add({ detail: 'Message has been Copy.', severity: S, summary: S, life: L }) }
if ("9001" == code) { toast.add({ detail: 'Please write your Message.', severity: E, summary: E, life: L }) }
if ("9002" == code) { toast.add({ detail: 'Please write your ID.', severity: E, summary: E, life: L }) }
if ("9003" == code) { toast.add({ detail: 'Message exceeds Size.', severity: E, summary: E, life: L }) }
if ("9999" == code) { toast.add({ detail: 'Server Error. please try again.', severity: E, summary: E, life: L }) }
}
/**
* Date Formater
*
* @param {*} date
* @returns [YYYY-MM-dd hh:mm:ss]
*/
function getFormatDate(date) {
const YYYY = String(date.getFullYear())
const MM = String((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1))
const dd = String(date.getDate() >= 10 ? date.getDate() : "0" + date.getDate())
const hours = String(date.getHours() >= 10 ? date.getHours() : "0" + date.getHours())
const minuts = String(date.getMinutes() >= 10 ? date.getMinutes() : "0" + date.getMinutes())
const seconds = String(date.getSeconds() >= 10 ? date.getSeconds() : "0" + date.getSeconds())
return "[" + YYYY + "-" + MM + "-" + dd + " " + hours + ":" + minuts + ":" + seconds + "]"
}
/**
* Null Check
*
* @param {*} str
* @returns default false
*/
function nullCheck(str) {
if ("" == str) { return true }
if (null == str) { return true }
if (str.replace(/\s/g, '').length < 1) { return true }
return false
}
export {
setToast,
getFormatDate,
nullCheck,
}
- LocalStorageUtil.js
import * as CmmUtil from '@/module/CmmUtil'
/**
* Local Storage Init
*
* @param {*} key
* @param {*} list (ref)
*/
function initLastMsg(key, list) {
localStorage.removeItem(key)
list.value = []
}
/**
* Local Storage GET Value
*
* @param {*} key
* @param {*} list (ref)
*/
function getLastMsg(key, list) {
if (null != localStorage.getItem(key)) {
list.value = JSON.parse(localStorage.getItem(key))
}
}
/**
* Local Storage SET Value
*
* @param {*} key
* @param {*} value (list in value)
* @param {*} list (ref)
*/
function setLastMsg(key, value, list) {
// 리스트 저장
if (!CmmUtil.nullCheck(value)) {
list.value.push({ "date": CmmUtil.getFormatDate(new Date()), "msg": value })
}
// 로컬 스토리지 저장
localStorage.setItem(key, JSON.stringify(list.value))
}
export {
getLastMsg,
setLastMsg,
initLastMsg,
}
- MsgSendCmp.vue
<template>
<div class="MsgSendCmp">
<h3>💌 Message</h3>
<div>
<Textarea v-model="inMsg" rows="5" cols="30" spellcheck="false" autoResize />
<div class="maxCheckDiv">
<h6 v-if="(inMsgSize <= MAX)">( {{ inMsgSize }} 자 / 최대 {{ MAX }} 자 )</h6>
<h6 class="maxInfo" v-else>( {{ inMsgSize }} 자 / 최대 {{ MAX }} 자 )</h6>
</div>
</div>
<div>
<Button v-if="(inMsgSize <= MAX)" label="Send" severity="Primary" raised @click="sendMsg()" />
<Button v-else label="Send" severity="danger" raised @click="sendMsg()" />
</div><br /><br />
<div class="messageDiv">
<h3>💬 지난 메시지</h3>
<div v-for="(obj, idx) in lastMsgList.slice().reverse()" :key="obj">
<Panel toggleable>
<template #header>
<div>
{{ obj.date }}
</div>
</template>
<template #footer>
<Button class="smallButton" label="Copy" severity="secondary" text raised @click="selectMsg(idx)" />
<Button class="smallButton" label="Delete" severity="danger" text raised @click="deleteMsg(idx)" />
</template>
<p>{{ obj.msg }}</p>
</Panel>
<br />
</div>
</div>
</div>
<Toast class="toast" />
</template>
<script setup>
/** Vue */
import { ref, computed, onMounted } from 'vue'
/** Util */
import * as CmmUtil from '@/module/CmmUtil'
import * as LocalStorageUtil from '@/module/LocalStorageUtil'
/** PrimeVue */
import Textarea from 'primevue/textarea'
import Button from 'primevue/button'
import Panel from 'primevue/panel'
/** PrimeVue Toast */
import Toast from 'primevue/toast';
import { useToast } from "primevue/usetoast"
/** Axios */
import * as AxiosModule from '@/module/AxiosModule'
onMounted(() => {
/** Local Storage GET Value */
LocalStorageUtil.getLastMsg(lastMsgKey, lastMsgList)
/** 사용자 입력 메세지 초기화 */
inMsgInit()
})
/** 입력 제한 글자수 */
const MAX = 20
/** 사용자 입력 메시지 */
const inMsg = ref("")
const inMsgSize = computed(() => inMsg.value.replaceAll("\n", "").length)
/** 지난 메시지 */
const lastMsgKey = "lastMsg"
const lastMsgList = ref([])
/** Toast */
const toast = useToast()
/** 사용자 입력 메세지 초기화 */
function inMsgInit() {
if (0 == lastMsgList.value.length) {
inMsg.value = ""
} else {
inMsg.value = lastMsgList.value[lastMsgList.value.length - 1].msg
}
}
/** 지난 메시지 선택 복사 */
function selectMsg(idx) {
inMsg.value = lastMsgList.value[lastMsgList.value.length - (idx + 1)].msg
CmmUtil.setToast(toast, "0002")
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }); // 스크롤 맨위 이동
}
/** 지난 메시지 선택 삭제 */
function deleteMsg(idx) {
// 리스트에서 삭제
lastMsgList.value.splice(lastMsgList.value.length - (idx + 1), 1)
/** Local Storage SET Value */
LocalStorageUtil.setLastMsg(lastMsgKey, null, lastMsgList)
CmmUtil.setToast(toast, "0001")
/** 사용자 입력 메세지 초기화 */
inMsgInit()
}
/** Send message */
async function sendMsg() {
/** Validation */
if (CmmUtil.nullCheck(inMsg.value)) { return CmmUtil.setToast(toast, "9001") }
if (CmmUtil.nullCheck(localStorage.getItem("ID"))) { return CmmUtil.setToast(toast, "9002") }
if (inMsgSize.value > MAX) { return CmmUtil.setToast(toast, "9003") }
/* 요청 값 설정 */
const REQ_DATA = {
"src": "WAS",
"dest": localStorage.getItem("ID"),
"cmd": "Ctrl",
"params": [inMsg.value]
}
/* CMS POST Send message API */
const resVO = await AxiosModule.sendPost(AxiosModule.API_LIST['CMS-SEND-MSG'], REQ_DATA)
if (resVO == 200) {
/** Local Storage SET Value */
LocalStorageUtil.setLastMsg(lastMsgKey, inMsg.value, lastMsgList)
CmmUtil.setToast(toast, "0000")
} else {
CmmUtil.setToast(toast, "9999")
}
}
</script>
▷ 결과 확인
*줄 바꿈은 글자 수에 포함하지 않는다
*글자 수 관련 Test 이외 생략
▷ 관련 글
728x90
728x90
'▶ Front-End > Vue.js' 카테고리의 다른 글
Vue3 기초 예제 - Local Storage (0) | 2023.11.14 |
---|---|
Vue3 기초 예제 - Toast 팝업(Primevue) (0) | 2023.11.13 |
Vue3 기초 예제 - Line Charts(Vue-ECharts) (0) | 2023.11.10 |
Vue3 기초 예제 - Bar Charts(Vue-ECharts) (0) | 2023.11.09 |
Vue3 기초 예제 프로젝트 정리 (0) | 2023.11.06 |
댓글