레이블이 vuetify인 게시물을 표시합니다. 모든 게시물 표시
레이블이 vuetify인 게시물을 표시합니다. 모든 게시물 표시

vuex local storage 갱신

# vuex store 를 다음과이 read/write 하는데, 데이터 구조를 변경했다.
# vuex store 사용 예
# store.js
state : {
  # before
  # mydata : 1
  # after
  mydata : {
     val1: "ysoftman",
     val2: 123,
  }
  mutations: {
    changeMyData(state, playload) {
      state.mydata.val1 = payload.val1;
      state.mydata.val2 = payload.val2;
    },
}

# abc.vue
import { eventBus } from "@/main";
methods: { 
 setMydata() {
   this.$store.commit("changeMyData", {
     val1: this.data.aaa,
     val2: this.data.bbb,
   });
   eventBus.$emit("setMydata", this.data);
 }
}

# 로컬 테스트에는 변경된 데이터 구조로 read/write 해서 문제가 없었는데,
# 실제 패키징 후 배포된 서버에서는 기존 데이터 구조로 남아 있어 문제가 발생했다.
chrome -> devtools -> application -> storage -> local storage
https://ysoftman.com -> key -> vuex -> value {"mydata": 1}

https://ysoftman.com -> clear 로 데이터를 모두 삭제후 사용하면 된다.

vue axios 모든 요청에 헤더,파라메터 추가하기

# 프로젝트내 모든 axios 요청 또는 응답에 공통으로 추가할 데이터(파라메터가,헤더)가 있는 경우
# 각 axios 구문 마다 일일히 추가하는 대신 axios intercepter 를 활용할 수 있다.
# 공통 파라메터 값이 vuetify store 에 저장된 경우
# vue 인스턴스 내부에서 axios.interceptors 를 명시해놓아야 한다.

# 얘시
# src/store.js 가 있고
# src/rouster/index.js 에 다음과 같이 추가한다.

import { store } from '@/store';

// axios 모든 요청 보내기전에 수행
// Add a request interceptor
axios.interceptors.request.use(function (config) {
  // Do something before request is sent
  if (config.params == null) {
    config.params = {};
  }
  config.params['ysoftman1'] = store.state.mydata.value;
  config.headers['fruit1'] = "lemon";
  config.headers['fruit2'] = "apple";
  console.log("----- config:", config);
  return config;
}, function (error) {
  // Do something with request error
  return Promise.reject(error);
});

// axios 모든 응답 리턴전에 수행
// Add a response interceptor
axios.interceptors.response.use(function (response) {
  // Any status code that lie within the range of 2xx cause this function to trigger
  // Do something with response data
  return response;
}, function (error) {
  // Any status codes that falls outside the range of 2xx cause this function to trigger
  // Do something with response error
  return Promise.reject(error);
});


vuetify v-data-table row selection

# vuetify v-data-table 에서 show-select 속성을 활성화면
# row 별로 check box 가 활성화 된다.
# v-model 지시자로 선택 한 row item 데이터를 파악할 수 있다.
<v-data-table
    :loading="loadingmyItem"
    loading-text="Loading... Please wait"
    :headers="myItemHeaders"
    :items="myItems"
    v-model="selectedItems"
    :single-select="false"
    show-select
></v-data-table>


# v-model 로 사용할 리스트 변수
export default {
  data() {
    return {
      selectedItems: [],
...


# data-table-select 값의 헤더를 사용해서 check box 속성을 커스터마이징 할 수 있다.
myItemHeaders: [
{
    text: "선택",
    value: "data-table-select",
    align: "center",
    class: "subheading font-weight-bold grey darken-2 white--text",
}


# [삽질 경험]
# row 선택(체크)해도 selectedItems 이 계속 [] 로 값이 변하지 않았다.
# v-model 바인딩을 :v-model 로 속성설정으로 잘못 사용한게 원인인데
# :v-model 해도 vuetify 에러메시지가 없어 몇시간을 삽질했다.ㅠ


vuetify upgrading from 1.x to 2.x

# vuetify 1.x -> 2.x 업그레이드 작업
# vuetify 최신버전(2.x) 및 sass 설치 : package.json 자동 변경
npm install --save vuetify@latest sass

# main.js 에서 vuetify 생성을 다음과 같이 변경
Vue.use(Vuetify);
const opts = {
  icons: {
    iconfont: 'md' || 'mdi'
  },
  theme: {
    themes: {
      light: {
        primary: '#01884e'
      }
    }
  }
};
new Vue({
  vuetify: new Vuetify(opts),
  // 기존 설정들...
});


##### 


# activator 는 다음과 같이 사용해야 한다.
<template v-slot:activator="{ on }">
    <v-btn v-on="on">...</v-btn>
</template>

# v-data-table 내의 aaa 필드값 재정의 하라면
# v-data-table 의 :headers 내의 value 이름이 
# :items 의 item내 필드명과 같아야 자동 렌더링이 된다.
# item 오브젝트를 destructuring 해서 aaa 필드인 경우 처리된다.
<template v-slot:item.aaa="{ item }"></template>

# v-list-group 에서 activator 는 자동으로 전달된다.
<v-list-item slot="activator"> -> <v-list-item>
<v-toolbar-title slot="activator">  -> <v-toolbar-title>


#####


# v-data-table 내에서 expanded row(아이템 아래에 확장 화면) 버튼 커스터마이징
# header 에 "data-table-expand" 이름의 값을 추가하고
headers : [
{
  text: "추가 정보",
  value: "data-table-expand",
}]
# v-data-table 내에서 다음과 같이 슬롯으로 expanded 관련 정보를 받아 처리한다.
<template v-slot:item.data-table-expand="{ item, isExpanded, expand }">
  <v-btn icon color="warning" @click="expand(true)" v-if="!isExpanded">expand</v-btn>
  <v-btn icon color="warning" @click="expand(false)" v-if="isExpanded">close</v-btn>
</template>


#####


# 컴포넌트들 이름 변경
<v-content> -> <v-main>
<v-toolbar app> -> <v-toolbar> # app 은 v-app-bar 컴포넌트를 사용해야 한다.
<v-toolbar-side-icon> -> <v-app-bar-nav-icon>
<v-list-tile> -> <v-list-item>
<v-list-tile-avatar> -> <v-list-item-avatar>
<v-list-tile-content> -> <v-list-item-content>
<v-list-tile-title> -> <v-list-item-title>
<v-list-tile-sub-title> -> <v-list-item-subtitle>
<v-data-table :rows-per-page-items> -> <v-data-table :footer-props="{'items-per-page-options':[-1]}"

# 이 밖에도 deprecated 되거나 사용방법등이 변경되는 경우 새로 UI를 구성해야 할 수 도 있다.
# 기타 자세한 내용 참고

vuetify v-data-table server pagination 사용시 client side sort 문제

# vuetify 2.x v-data-table 를 
# server pagination(서버에서 특정 단위로 데이터를 주는 경우)로 사용했는데,
# 클라에서는 받은 데이터 내에서 sort(정렬)가 동작 하지 않는다.
# :server-items-length(전체 데이터 개수, 몇개의 페이지로 표시해야 할지 알기 위해 필요하다.)
# 속성을 제거하면 정렬 기능이 동작했다.

# stackoverflow 에 나와 같은 문제를 겪는 사람이 있었다.


# vuetify 입장은 server pagination 은 
# 서버에서 현재 페이지에 해당하는 일부 데이터만 받고
# 이 일부 데이터를 정렬 하는것은 쓸모 없다고 한다.

# 그래도 적은 일부 데이터 내에서라도 정렬 기능은 필요해 보이는데, 지원이 아쉽다.

vuetify sidebar 사용시 횡스크롤 문제

# vuetify 로
# 위쪽은 v-toolbar 를 위치시키고
# 왼쪽에 v-navigation-drawer(sidebar)를 위치시키고
# 오른쪽에 v-data-table 을 위치하도록 구성했다.
# v-data-table 의 컬럼 개수가 많아
# 브라우저의 폭을 줄일때 맨 오른쪽 부분이 보이지 않는 문제가 발생했다.
# 원래 v-data-table 자체에서 횡스크롤이 가능하고
# 브라우저 폭이 일정 크기 아래로 줄어 들면
# breakpoint 로직이 작동해 아래쪽으로 컬럼이 적절하게 보여진다.
# 하지만 v-data-table 에서도 sidebar 폭만큼 오른쪽 더 스크롤 되지 않는다.
# 원인은 div 의 overflow css 속성이 안돼 발생한것으로
# scroll 또는 auto 로 명시해야 화면 횡스크롤이 된다.(이걸 몰라 계속 삽질ㅠ)
vi app.vue
<style>
/* toolbar, sidebar 는 고정하고 오른쪽 영역에서 화면 횡스크롤 하기 위한 css */
.top-view {
  position: fixed; /* 스크롤 해도 위치 고정 */
  width: 100%; /* 전체 너비 채우기 */
  z-index: 99; /* 같은 위치에 여러 엘리먼트가 위치할때 이 값이 클수록 앞쪽(위로 덮는)으로 온다. vuetify default z-index : 5 */
}
.body-view {
  display: flex; /* 모든 요소를 한줄에 표시 */
  margin-top: 50px; /* top-view 높이 감안해서 50px 만큼 아래에 위치 */
}
.left-view {
  display: flex; /* 모든 요소를 한줄에 표시 */
  position: fixed; /* 스크롤 해도 위치 고정 */
  height: 100%; /* sidebar 높이를 전체 채우기 */
}
.right-view {
  width: 100%; /* 오른쪽 영역의 폭을 전체 채우기 */
  overflow: auto; /* 또는 scroll 값, 횡스크롤 가능하도록 */
  margin-left: 100px; /* sidebar 폭 감안해서 100px 만큼 오른쪽에 위치 */
}
</style>
<template>
  <v-app>
    <div class="top-view>
      <ysoftmanToolbar />
    </div>
    <div class="body-view">
      <div class="left-view">
        <ysoftmanNavigation />
      </div>
      <div class="right-view">
        <ysoftmanDatatable />
      </div>
    </div>
  </v-app>
</template>

<script>
import ysoftmanToolbar from '@/components/ysoftmanToolbar';
import ysoftmanNavigation from '@/components/ysoftmanNavigation';
import ysoftmanDataTable from '@/components/ysoftmanDataTable';
export default {
  name: 'App',
  components: {
    ysoftmanToolbar,
    ysoftmanNavigation,
    ysoftmanDataTable,
  },
  data() {
    return {};
  },
};
</script>