[nuxt] [rails] filter 메서드를 사용하여 다중 계층 선택 상자를 비동기식으로 구현

18374 단어 nuxt.jsRails
filter 메소드로 다계층의 셀렉트 박스를 비동기로 구현하는 일이 있었으므로 복습이 나중에 기사로 합니다.

전제 조건



전면: nuxt
뒤: rails
api 통신이 완료되었습니다.

데이터 구성은 아래 기사를 참고로 한다
Rails * Vue.js * Ajax에서 다중 계층 카테고리를 만든 이야기

완제품


rails 측 구현


  • seed_fu로 데이터 생성
  • 라우팅 생성
  • 컨트롤러 생성
  • jbuilder에서 json으로 데이터를 반환합니다.

    001_category.rb
    Category.seed(:id,
      { id: 100, name: '親1'},
      { id: 110, name: '親1の子1'},
      { id: 111, name: '親1の子1の孫1'}, { id: 112, name: '親1の子1の孫2'}, { id: 113, name: '親1の子1の孫3'},
      { id: 120, name: '親1の子2'},
      { id: 121, name: '親1の子2の孫1'}, { id: 122, name: '親1の子2の孫2'}, { id: 123, name: '親1の子2の孫3'},
      { id: 130, name: '親1の子3'},
      { id: 131, name: '親1の子3の孫1'}, { id: 132, name: '親1の子3の孫2'}, { id: 133, name: '親1の子3の孫3'},
    
      { id: 200, name: '親2'},
      { id: 210, name: '親2の子1'},
      { id: 211, name: '親2の子1の孫1'}, { id: 212, name: '親2の子1の孫2'}, { id: 213, name: '親2の子1の孫3'},
      { id: 220, name: '親2の子2'},
      { id: 221, name: '親2の子2の孫1'}, { id: 222, name: '親2の子2の孫2'}, { id: 223, name: '親2の子2の孫3'},
      { id: 230, name: '親2の子3'},
      { id: 231, name: '親2の子3の孫1'}, { id: 232, name: '親2の子3の孫2'}, { id: 233, name: '親2の子3の孫3'}
    )
    

    routes.rb
    Rails.application.routes.draw do
      resources :categories, only: %i[index]
    end
    

    categories_controller.rb
    class CategoriesController < BaseController
      def index
        @categories = Category.all
      end
    end
    

    index.jbuilder
    json.categories @categories do |category|
      json.extract! category, :id, :name
    end
    

    nuxt 측 구현



    nuxt는 vuestify 이라는 머티리얼 디자인 컴포넌트 프레임워크를 사용

    category.vue
    <template>
      <div>
        <v-select
          label="親カテゴリー"
          :items="parentCategory"
          item-text="name"
          item-value="id"
          v-model="parentSelected"
        />
    
        <v-select
          label="子カテゴリー"
          :items="childCategory"
          item-text="name"
          item-value="id"
          v-model="childrenSelected"
        />
    
        <v-select
          label="孫カテゴリー"
          :items="grandChildCategory"
          item-text="name"
          item-value="id"
          v-model="grandChildrenSelected"
        />
      </div>
    </template>
    
    <script>
    export default {
      mounted() {
        this.fetchCategory()
      },
    
      data: () => {
        return {
          categories: [],
          parentSelected: '',
          childrenSelected: '',
          grandChildrenSelected: '',
        }
      },
    
      computed: {
        parentCategory() {
          return this.categories.filter((category) => category.id % 100 === 0)
        },
    
        childCategory() {
          if (this.parentSelected === '') {
            return []
          }
    
          return this.categories.filter((category) => {
                    // 100の位が同じcategory
            return (Math.floor(category.id  / 100) === Math.floor(this.parentSelected / 100) &&
                    // 1の位が0のcategory
                    category.id % 10 === 0 &&
                    // 親カテゴリーと一致しないcategory
                    category.id !== this.parentSelected)
            })
        },
    
        grandChildCategory() {
          if (this.childrenSelected === '') {
            return []
          }
    
          return this.categories.filter((category) => {
                    // 10の位が一致するcategory
            return (Math.floor(category.id  / 10) === Math.floor(this.childrenSelected / 10) &&
                    // 1の位が0ではないのcategory
                    category.id % 10 !== 0)
          })
        }
      },
    
      methods: {
        fetchCategory() {
          const url = 'api/categories'
          this.$axios
            .$get(url)
            .then((response) => {
              this.categories = response.categories
            })
            .catch((errors) => {
              console.log(errors)
            })
        }
      }
    }
    </script>
    
  • mounted에서 fetchCategory 호출
  • 선택 상자 옵션을 computed에서 각각 정의
  • 각 선택 상자에 v-model 설정
  • 부모 v-model 변경 -> 하위 카테고리 옵션 변경
  • 아이의 v-model이 변경 -> 손자 카테고리의 옵션이 변경

  • filter는 이렇게 사용합니다.
    [検証したいデータ].filter((1データ) => 条件式)
    

    상위 카테고리의 예를 살펴 보겠습니다.
    // 親カテゴリー
    <v-select
      label="親カテゴリー"
      :items="parentCategory"
      item-text="name"
      item-value="id"
      v-model="parentSelected"
    />
    
    // オプション定義
    parentCategory() {
      return this.categories.filter((category) => category.id % 100 === 0)
      // 100 % 100 = 0, 110 % 100 = 10, 111 % 100 = 11, 200 % 100 = 0
    },
    
    :items="オプションのデータ" 그래서 computed 안에 있는 parentCategorythis.categories에는 rails에서 정의한 Category.all의 데이터가 들어 있습니다.
    category에는 { id: 100, name: '親1' } 와 같이 하나의 데이터가 들어 있습니다.
    그 데이터의 id를 100으로 나눈 때의 너무가 0과 일치하는 데이터를 돌려주는 처리가 되어 있으므로
    이 경우 id가 100, 200, 300...인 레코드가 반환됩니다.

    이상입니다.

    filter의 조건식을 좀 더 잘 기술할 수 있을 것 같은 생각이 듭니다만. . .
    다른 좋은 방법이 있다면 코멘트에서 알려주세요!

    좋은 웹페이지 즐겨찾기