📘 Frontend/Vue

Vue - 학습 기록 앱 만들기 5 : Input Form 구현

신건우 2023. 8. 5. 19:09

Resource Form

지금까지 더미 데이터를 이용해 Resource를 만들었지만 이제부터 Form을 이용해 사용자로부터 입력을 받아서 Form을 제출해, Resource를 배열에 동적으로 추가해보겠습니다.


하나의 div마다 입력 값을 정해주고 제목, 내용(3줄), 링크를 입력할 수 있는 공간과 제출 버튼을 만들어 주었습니다.

<template>  
  <base-card>  
    <form>  
      <!-- Title -->  
      <div class="form-control">  
        <lable for="title">제목</lable>  
        <input  
          type="text"  
          id="title"  
          name="title"  
        />  
      </div>  
      <!-- Description -->  
      <div class="form-control">  
        <lable for="description">설명</lable>  
        <textarea  
        id="description"  
        name="description"  
        rows="3"  
        ></textarea>  
      </div>  
      <!-- Title -->  
      <div class="form-control">  
        <lable for="link">링크</lable>  
        <input  
            type="url"  
            id="link"  
            name="link"  
        />  
      </div>  
      <!--Submit Button -->  
      <div>  
        <base-button type="submit">학습 추가</base-button>  
      </div>  
    </form>  
  </base-card>  
</template>  

<script>  
import BaseCard from "@/components/UI/BaseCard";  
import BaseButton from "@/components/UI/BaseButton";  
export default {  
  components: {BaseButton, BaseCard}  
}  
</script>  

<style scoped>  
label {  
  font-weight: bold;  
  display: block;  
  margin-bottom: 0.5rem;  
}  

input,  
textarea {  
  display: block;  
  width: 100%;  
  font: inherit;  
  padding: 0.15rem;  
  border: 1px solid #ccc;  
}  

input:focus,  
textarea:focus {  
  outline: none;  
  border-color: #3a0061;  
  background-color: #f7ebff;  
}  

.form-control {  
  margin: 1rem 0;  
}  
</style>

Form 양식 적용

img


이제 입력은 받았으니 입력값을 배열에 넣어서 출력해보겠습니다.

AddResource에서 Custom Event를 발생시켜 상위 컴포넌트로 수신하게 해도 되지만,

AddResource 컴포넌트가 동적으로 등록되어 있기 때문에 이 방법은 어렵습니다.

일단 AddResource 컴포넌트에 입력값을 가져올 수 있도록 ref 속성을 사용해줍니다.

AddResource.vue

<form>  
  <!-- Title -->  
  <div class="form-control">  
    <lable for="title">제목</lable>  
    <input  
      type="text"  
      id="title"  
      name="title"  
      ref="titleInput"  
    />  
  </div>  
  <!-- Description -->  
  <div class="form-control">  
    <lable for="description">설명</lable>  
    <textarea  
    id="description"  
    name="description"  
    rows="3"  
    ref="descInput"  
    ></textarea>  
  </div>  
  <!-- Title -->  
  <div class="form-control">  
    <lable for="link">링크</lable>  
    <input  
        type="url"  
        id="link"  
        name="link"  
        ref="linkInput"  
    />  
  </div>  
  <!--Submit Button -->  
  <div>  
    <base-button type="submit">제출</base-button>  
  </div>  
</form>

그래서 이번에도 provide/inject를 써서 주입해보겠습니다.

주입하기 전에 TheResource.vue에서 최종 리소스들을 관리하므로 리소스 추가 함수를 작성하겠습니다.

그리고, 하위 컴포넌트로 주입해주기 위해 provide에도 함수를 포인팅 해줍니다.

TheResources.vue

methods: {  
  setSelectedTab(tab) {  
    this.selectedTab = tab;  
  },  
  addResource(title, description, url) {  
    const newResource = {  
      id: new Date().toISOString(),  
      title: title,  
      description: description,  
      link: url  
    };  
    // 배열의 맨앞에 추가 (unshift)
    this.storedResources.unshift(newResource);  
    // 리소스를 추가할때마다 탭이 바뀌게 함  
    this.selectedTab = 'stored-resources';  
  }  
},  

provide() {  
  return {  
    resources: this.storedResources,  
    addResource: this.addResource  
  };  
},

그리고 이제 TheResource의 함수를 inject 받고 form에 함수를 포인팅 해주면 양식 제출이 되고 리스트에 나옵니다.

AddResource.vue

<form @submit.prevent="submitData">

...

inject: ['addResource'],  

methods: {  
  submitData() {  
    const enteredTitle = this.$refs.titleInput.value;  
    const enteredDesc = this.$refs.descInput.value;  
    const enteredLink = this.$refs.linkInput.value;  

    this.addResource(enteredTitle, enteredDesc, enteredLink);  
  }  
}

결과물

img