Airtable, Vue + Vuetify로 간단한 CRUD 앱 구축




에어테이블이란?



익숙하지 않다면 Airtable은 Google 스프레드시트가 관계형 DB를 만난 것과 같습니다. 무엇보다도 무료이며 사용하기 쉬운 GUI(코더가 없는 사용자용)와 데이터용 API가 있습니다!

데이터베이스 생성은 Airtable에 "시트"를 추가하는 간단한 문제입니다. 예를 들어 "Example"이라는 단일 테이블 이름이 있는 "Somedata"라는 이름의 Airtable이 있습니다...



Airtable이 제공하는 다양한 데이터 유형을 사용하여 필요한 모든 열/필드를 추가합니다.

모든 Airtable에는 API가 있습니다😎



시트와 몇 개의 열을 추가했으면 Airtable UI의 오른쪽 상단 모서리에 있는 ?(도움말) 아이콘을 클릭하고 'API 설명서'를 선택합니다. Airtable의 API에 대한 문서가 표시됩니다...



간단한 CRUD API에서 예상할 수 있듯이 List, Read, Create, Update 및 Delete를 위한 API 메서드가 있습니다. 각 API 엔드포인트는 Airtable ID(일명 "앱 ID")와 테이블 이름으로 구성된 URL입니다. API 요청에는 API 문서에서도 찾을 수 있는 고유한 API 키가 필요합니다.

예를 들어 "Example"이라는 이름의 "Somedata"(앱 ID: appsAka4wMdRoGCUc) 테이블에 대한 API URL은 다음과 같습니다.

API 끝점의 URL 예

https://api.airtable.com/v0/appsAka4wMdRoGCUc/Example



Vuetify를 사용한 Vue 앱



Vuetify's awesome component framework 을 사용하여 Vue 앱을 만들어 보겠습니다. Airtable 설정을 유지하기 위해 몇 가지 상수를 추가했습니다(나중에 사용함).

<script>
const apiToken = "keyZoaskXXXX" // use your own key!
const airTableApp = "appXJzFFs2zgj4X5C"
const airTableName = "Example"

new Vue({
  el: '#app',
  vuetify: new Vuetify(),   
})
</script>

<template>
<div id="app">
    <v-app>
        <v-content>
            <h2>
                Vuetify CRUD Example
            </h2>
        </v-content>
    </v-app>
</div>
</template>



Axios 및 Vuetify DataTable



Airtable API와의 통신에 Vue Axios을 사용합니다. VuetifyDataTable component는 데이터를 표시하는 데 사용되며 기본 제공 페이지 매김, 정렬 및 검색 기능을 제공합니다.



레코드를 생성하거나 편집하기 위해 이중 목적Dialog component을 사용합니다.




지금까지의 모든 것은 표준 Vue, Veutify, Axios 상용구입니다. 이제 CRUD 앱에 대해 자세히 살펴보겠습니다.




1. 먼저 템플릿 마크업에서 v-data-table를 설정해 보겠습니다.

<div id="app">
    <v-app>
        <v-content class="container align-center px-1">
            <h2 class="font-weight-light mb-2">
                Vuetify CRUD Example
            </h2>
            <v-card>
                <v-data-table 
                :headers="headers" 
                :items="items">
                </v-data-table>
            </v-card>
        </v-content>
    </v-app>
</div>

2. Vuetify DataTable에서 사용되는 data()items에 대한 Vueheaders를 추가합니다. headers는 Airtable 예제 열에 해당합니다.

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data () {
    return {
        headers: [
            { text: 'Id', value: 'id' },
            { text: 'Name', value: 'Name' },
            { text: 'Details', value: 'details', sortable: false, width:"100" },
            { text: 'URL', value: 'url', name:'url', width:"180" },
            { text: 'Action', value: 'actions', sortable: false },
        ],
        items: [],
        dialog: false, // used to toggle the dialog
        editedItem: {} // empty holder for create/update ops
    }
  },
})


Airtable API에서 읽기



3. 다음으로 Axios를 사용하여 Airtable API에 GET 요청(가져오기)을 수행합니다. 다음은 '예제'의 모든 레코드(행)를 읽는 메소드loadItems()입니다. Vue 구성 요소가 mounted() ...

  ...
  mounted() {
    this.loadItems()
  },
  methods: {
    loadItems() {
        this.items = []
        axios.get(`https://api.airtable.com/v0/${airTableApp}/${airTableName}`,
            { headers: { Authorization: "Bearer " + apiToken }})
        .then((response) => {
            // load the API response into items for datatable
            this.items = response.data.records.map((item)=>{
                return {
                    id: item.id,
                    ...item.fields
                }
            })
        }).catch((error) => {
            console.log(error)
        })
    },

위에서 우리는 이제 이전에 생성된 Airtable const를 사용했습니다.

Airtable API의 응답 처리



API 응답 데이터는 다음과 같습니다...

Airtable API의 레코드 응답 나열

{
    "records": [
        {
            "id": "recqbv38i4CbirwP4",
            "fields": {
                "Cat": "bar",
                "URL": "https://codeply.com",
                "Lat": -71.39241,
                "Details": "Frontend editor online",
                "Name": "Codeply",
                "Lon": 41.46,
                "Client": "John Doe"
            },
            "createdTime": "2020-03-25T18:33:52.000Z"
        },
        {
            "id": "recsEjAfLlkKH5rcC",
            "fields": {
                "Cat": "lodging",
                "URL": "https://themestr.app",
                "Lat": -71.39,
                "Details": "Theme builder and customizer for Bootstrap 4",
                "Name": "Themestr.app",
                "Lon": 41.67,
                "Client": "Mary Janes"
            },
            "createdTime": "2020-03-25T18:33:52.000Z"
        },
        ... more rows...
    ]
}

위에서 테이블 데이터가 records 배열에 포함되어 있고 행 데이터가 fields 속성에 중첩되어 있다는 점에 주목하는 것이 중요합니다. 이것이 loadItems() 메서드가 다음과 같이 데이터this.items에 할당하는 이유입니다.

         this.items = response.data.records.map((item)=>{
             return {
                 id: item.id,
                 ...item.fields
             }
         })

이제 this.items 배열에는 v-data-table가 반복하기 쉬운 평평한 구조가 있습니다.

   [
        {
            "id": "recqbv38i4CbirwP4",
            "Cat": "bar",
            "URL": "https://codeply.com",
            "Lat": -71.39241,
            "Details": "Frontend editor online",
            "Name": "Codeply",
            "Lon": 41.46,
            "Client": "John Doe".
            "createdTime": "2020-03-25T18:33:52.000Z"
        },
        ... more rows...
   ]

Airtable API로 데이터 보내기(POST 및 PUT)



4. saveItem (생성 또는 업데이트) 및 deleteItem에 대한 방법을 계속 진행합니다.

  ,
  methods: {
    loadItems() {
        ...
    },
    saveItem(item) {
        /* this is used for both creating and updating API records
         the default method is POST for creating a new item */

        let method = "post"
        let url = `https://api.airtable.com/v0/${airTableApp}/${airTableName}`
        let id = item.id

        // airtable API needs the data to be placed in fields object
        let data = {
            fields: item
        }

        if (id) {
            // if the item has an id, we're updating an existing item
            method = "patch"
            url = `https://api.airtable.com/v0/${airTableApp}/${airTableName}/${id}`

            // must remove id from the data for airtable patch to work
            delete data.fields.id
        }

        // save the record
        axios[method](url,
            data,
            { headers: { 
                Authorization: "Bearer " + apiToken,
                "Content-Type": "application/json"
            }
        }).then((response) => {
            if (response.data && response.data.id) {
                // add new item to state
                this.editedItem.id = response.data.id
                if (!id) {
                    // add the new item to items state
                    this.items.push(this.editedItem)
                }
                this.editedItem = {}
            }
            this.dialog = !this.dialog
        })
    },
    deleteItem(item) {
        let id = item.id
        let idx = this.items.findIndex(item => item.id===id)
        if (confirm('Are you sure you want to delete this?')) {
            axios.delete(`https://api.airtable.com/v0/${airTableApp}/${airTableName}/${id}`,
                { headers: { 
                    Authorization: "Bearer " + apiToken,
                    "Content-Type": "application/json"
                }
            }).then((response) => {
                this.items.splice(idx, 1)
            })
        }
    },

5. 이제 데이터 편집을 위한 양식 입력이 포함된 대화 상자를 연결합니다. 레코드를 생성하기 위한 '새로 만들기' 버튼도 포함되어 있습니다. v-dialog 바로 아래에 v-data-table 마크업을 추가합니다...

       <v-card>
            <v-data-table 
             :headers="headers" 
             :items="items" 
             >
             </v-data-table>
             <!-- this dialog is used for both create and update -->
             <v-dialog v-model="dialog">
                  <template v-slot:activator="{ on }">
                    <div class="d-flex">
                        <v-btn color="primary" dark v-on="on">
                            New 
                        </v-btn>
                    </div>
                  </template>
                  <v-card>
                    <v-card-title>
                        <span v-if="editedItem.id">Edit {{editedItem.id}}</span>
                        <span v-else>Create</span>
                    </v-card-title>
                    <v-card-text>
                        <v-row>
                          <v-col cols="12" sm="4">
                            <v-text-field v-model="editedItem.Name" label="Name"></v-text-field>
                          </v-col>
                          <v-col cols="12" sm="8">
                            <v-text-field v-model="editedItem.Details" label="Details"></v-text-field>
                          </v-col>
                          <v-col cols="12" sm="12">
                            <v-text-field v-model="editedItem.URL" label="URL"></v-text-field>
                          </v-col>
                        </v-row>
                    </v-card-text>
                    <v-card-actions>
                      <v-spacer></v-spacer>
                      <v-btn color="blue" text @click="showEditDialog()">Cancel</v-btn>
                      <v-btn color="blue" text @click="saveItem(editedItem)">Save</v-btn>
                    </v-card-actions>
                  </v-card>
            </v-dialog>
       </v-card>

6. 그런 다음 대화 상자 표시를 토글하는 방법을 추가합니다.

 methods: {
    showEditDialog(item) {
        this.editedItem = item||{}
        this.dialog = !this.dialog
    },
    loadItems() {...},


7. 다음으로 v-data-table item.actions 슬롯 템플릿을 사용자 지정하여 showEditDialog() 기존 레코드를 편집하는 방법에 연결합니다. deleteItem() 에 대한 아이콘/버튼도 추가합니다.

 <v-data-table 
    :headers="headers" 
    :items="items">
        <template v-slot:item.actions="{ item }">
            <div class="text-truncate">
              <v-icon
                class="mr-2"
                @click="showEditDialog(item)"
                color="primary" 
              >
                mdi-pencil
              </v-icon>
              <v-icon
                @click="deleteItem(item)"
                color="pink" 
              >
                mdi-delete
              </v-icon>
          </div>
        </template>
    </v-data-table>




완성품😏은 the working Vuetify + Airtable CRUD example 입니다.

이에 대한 귀하의 생각을 댓글로 알려주시고 여기에서 전체 소스 코드를 가져오십시오: https://codeply.com/p/Vx4dDt5c9G/vuetify-crud-example

좋은 웹페이지 즐겨찾기