세모튜브

小程序 앱만들기 - 7-1 : 검색 페이지 만들기 - tab 구현하기 본문

미니프로그램-小程序/위챗-관광정보 앱

小程序 앱만들기 - 7-1 : 검색 페이지 만들기 - tab 구현하기

iDevKim 2020. 5. 21. 17:11

유튜브강좌 : youtu.be/4AOaL0HnD48

 

기본 레이아웃

조건버튼 클릭시

 

Tab 정의

기본 변수 선언

- Tab의 정의 : class Tab {...}

- 통합검색 : tabArray: [0]

- 행사검색 : tabArray: [1]

- 숙박검색 : tabArray: [2]

//search.js
const api = require("../../utils/api.js");
const def = require("../../utils/def.js");
const util = require("../../utils/util.js");
const code = require("../../utils/code.js");
const app = getApp()

class Tab {
  constructor(name) {
    this.name = name;
    this.conArray = [];//condition : 조건Array
    this.keyword = "";
    this.resArray = [];//result : 결과Array
    this.numOfRows = 20;//페이지당 갯수
    this.pageNo = 0;//현재 페이지
    this.pageTot = 0;//전체 페이지 = totalCnt / numOfRows
    this.listYN = "N";//(Y=목록, N=개수)
  }
}

Page({
  data: {
    StatusBar: app.globalData.StatusBar,
    CustomBar: app.globalData.CustomBar,
    TabCur: 0,
    tabArray: [],
  },
  
  initData(){
    this.setData({
      tabArray: [
        new Tab("통합검색"),
        new Tab("행사검색"),
        new Tab("숙박검색")
      ],
    })
  },
  
  onLoad: function () {
    this.initData();
  },
  
  onShow() {
  },
  
  tabSelect(e) {
    this.setData({
      TabCur: e.currentTarget.dataset.id,
    })
  },
})

레이아웃 정의

<!--search.wxml-->

<!-- 상단 네비게이션바 부분 -->
<view class="cu-custom" style="height:{{CustomBar}}px">
  <view class="cu-bar fixed bg-green" style="height:{{CustomBar}}px;padding-top:{{StatusBar}}px;">
    <view class="action">
      <text class="">{{tabArray[TabCur].pageNo}} / {{tabArray[TabCur].pageTot}}</text>
    </view>
    <view class="content" style="top:{{StatusBar}}px">
      <text class="">검색</text>
    </view>
  </view>
</view>

<!-- Tab부분 -->
<view class="fixed flex bg-gray" style="top:{{CustomBar}}px;">
<!-- 조건버튼 -->
  <view class="basis-xs flex align-center justify-center" bindtap="showModal" data-target="keyword">
    <button class="cu-btn round bg-red shadow">조건</button>
  </view>
<!-- tab   -->
  <view class="basis-xl">
    <scroll-view scroll-x class="bg-gray nav">
      <view class="flex text-center">
        <view class="cu-item flex-sub {{index==TabCur?'text-green cur':''}}" wx:for="{{tabArray}}" wx:key="index" bindtap="tabSelect" data-id="{{index}}">
          {{tabArray[index].name}}
        </view>
      </view>
    </scroll-view>
  </view>
</view>

<!-- 통합검색 scroll-view -->
<block wx:if="{{TabCur==0}}">
  <scroll-view wx:if="{{tabArray[TabCur].resArray.length}}" scroll-y="{{modalName==null}}" class="page {{modalName!=null?'show':''}}">
  
  검색결과 리스트
  
  </scroll-view>
  <view wx:else class="padding-top-xl text-center text-shadow text-grey">
    <text class="text-bold text-xxl">데이터가 없습니다.</text>
  </view>
</block>
<!-- 행사검색 scroll-view -->
<block wx:if="{{TabCur==1}}">
  <scroll-view wx:if="{{tabArray[TabCur].resArray.length}}" scroll-y="{{modalName==null}}" class="page {{modalName!=null?'show':''}}">
  
  검색결과 리스트
  
  </scroll-view>
  <view wx:else class="padding-top-xl text-center text-shadow text-grey">
    <text class="text-bold text-xxl">데이터가 없습니다.</text>
  </view>
</block>
<!-- 숙박검색 scroll-view -->
<block wx:if="{{TabCur==2}}">
  <scroll-view wx:if="{{tabArray[TabCur].resArray.length}}" scroll-y="{{modalName==null}}" class="page {{modalName!=null?'show':''}}">
  
  검색결과 리스트
    
  </scroll-view>
  <view wx:else class="padding-top-xl text-center text-shadow text-grey">
    <text class="text-bold text-xxl">데이터가 없습니다.</text>
  </view>
</block>

스타일시트 정의

/* pages/search/search.wxss */
page {
  padding-top: 100rpx;
  background-color: white;
}

.fixed {
  position: fixed;
  width: 100%;
  top: 0;
  z-index: 1024;
}

.basis-90 {
  flex-basis: 90%;
}

 

실행결과

 

조건버튼 모달상자 정의

- 모달상자에 사용될 코드변수 정의

  initData(){
    this.setData({
      tabArray: [
        new Tab("통합검색"),
        new Tab("행사검색"),
        new Tab("숙박검색")
      ],
    })
    
    let resCode = code.init();
// 통합검색     
    this.setData({
      [`tabArray[0].contentIndex`]: 0,
      [`tabArray[0].categoryIndex`]: [0, 0, 0],
      [`tabArray[0].areaIndex`]: [0, 0],
      [`tabArray[0].arrangeIndex`]: 0,
      [`tabArray[0].contentArray`]: resCode[0],
      [`tabArray[0].categoryArray`]: resCode[1],
      [`tabArray[0].areaArray`]: resCode[2],
      [`tabArray[0].arrangeArray`]: resCode[3],
      [`tabArray[0].keyword`]: "",
    })
   },

- 조건버튼을 클릭시 bindtap="showModal" 함수가 호출되므로 아래와 같이 정의.

// modal 처리
//////////////////////////////////////////////////////  
  showModal(e) {
    if(!wx.getStorageSync(def.CategoryCode) && !wx.getStorageSync(def.AreaCode)) {
      wx.showModal({
        title: '코드가 존재하지 않습니다.',
        confirmColor: '#b4282d',
        content: '코드관리 페이지로 이동합니다.',
        showCancel: false,
        confirmText: "확인",
        complete: function () {
          wx.navigateTo({
            url: '/pages/user/code/code',
          })
        }
      })
    } else {
      this.setData({
        modalName: e.currentTarget.dataset.target
      })
    }
  },
  hideModal(e) {
    this.setData({
      modalName: null
    })
  },

모달상자 레이아웃 정의

<!-- modal -->
<!-- ================================================================================================ -->
<!-- 통합검색 modal -->
<view class="cu-modal drawer-modal justify-end {{modalName=='keyword'?'show':''}}" bindtap="hideModal">
  <view class="cu-dialog basis-90 text-right" catchtap style="top:{{CustomBar}}px;height:calc(100vh - {{CustomBar}}px)">
    <form>
      <view class="cu-form-group">
        <view class="title">타입</view>
        <picker bindchange="contentChange" value="{{tabArray[TabCur].contentIndex}}" range-key="name" range="{{tabArray[TabCur].contentArray}}">
          <view class="picker">
          {{tabArray[TabCur].contentArray[tabArray[TabCur].contentIndex].name}}
          </view>
        </picker>
      </view>
      <view class="cu-form-group">
        <view class="title">분류</view>
        <picker mode="multiSelector" bindcolumnchange="categoryColumnChange" value="{{tabArray[TabCur].categoryIndex}}" range-key="name" range="{{tabArray[TabCur].categoryArray}}">
          <view class="picker">
            {{tabArray[TabCur].categoryArray[0][tabArray[TabCur].categoryIndex[0]].name}},
            {{tabArray[TabCur].categoryArray[1][tabArray[TabCur].categoryIndex[1]].name}},
            {{tabArray[TabCur].categoryArray[2][tabArray[TabCur].categoryIndex[2]].name}}
          </view>
        </picker>
      </view>
      <view class="cu-form-group">
        <view class="title">지역</view>
        <picker mode="multiSelector" bindcolumnchange="areaColumnChange" value="{{tabArray[TabCur].areaIndex}}" range-key="name" range="{{tabArray[TabCur].areaArray}}">
          <view class="picker">
            {{tabArray[TabCur].areaArray[0][tabArray[TabCur].areaIndex[0]].name}},
            {{tabArray[TabCur].areaArray[1][tabArray[TabCur].areaIndex[1]].name}}
          </view>
        </picker>
      </view>
      <view class="cu-form-group">
        <view class="title">검색어</view>
        <input type="text" value="{{tabArray[0].keyword}}" bindinput="keywordChange" placeholder="두글자 이상 검색어를 입력해주세요"></input>
      </view>
      <view class="cu-form-group">
        <view class="title">정렬</view>
        <picker bindchange="arrangeChange" value="{{tabArray[TabCur].arrangeIndex}}" range-key="name" range="{{tabArray[TabCur].arrangeArray}}">
          <view class="picker">
          {{tabArray[TabCur].arrangeArray[tabArray[TabCur].arrangeIndex].name}}
          </view>
        </picker>
      </view>
    </form>
    <view class="padding flex flex-direction">
      <button class="cu-btn bg-red margin-tb-sm lg" bindtap="bindSearch">검색</button>
    </view>
  </view>
</view>

실행결과

 

모달상자 내부항목 bind change 처리

타입 : bindchange="contentChange"

분류 : bindcolumnchange="categoryColumnChange"

지역 : bindcolumnchange="areaColumnChange"

검색어 : bindinput="keywordChange"

정렬 : bindchange="arrangeChange"

// Bind Change 처리
////////////////////////////////////////////////////////////////////////////////
  contentChange(e) {
    let contentId = e.detail.value;
    this.setData({
      [`tabArray[${this.data.TabCur}].contentIndex`]: contentId,
      [`tabArray[${this.data.TabCur}].categoryIndex`]: [0, 0, 0],
      [`tabArray[${this.data.TabCur}].categoryArray`]: code.initCategoryArray(contentId),//contentId변경으로 인한 재설정.
    })
  },
  categoryColumnChange(e) {
    let contentIndex = this.data.tabArray[this.data.TabCur].contentIndex;
    let categoryIndex = this.data.tabArray[this.data.TabCur].categoryIndex;
    let categoryArray = this.data.tabArray[this.data.TabCur].categoryArray;
    let res = code.categoryColumnChange(contentIndex, categoryIndex, categoryArray, e);
    this.setData({
      [`tabArray[${this.data.TabCur}].categoryIndex`]: res[0],
      [`tabArray[${this.data.TabCur}].categoryArray`]: res[1],
    })
  },
  areaColumnChange(e) {
    let areaIndex = this.data.tabArray[this.data.TabCur].areaIndex;
    let areaArray = this.data.tabArray[this.data.TabCur].areaArray;
    let res = code.areaColumnChange(areaIndex, areaArray, e);
    this.setData({
      [`tabArray[${this.data.TabCur}].areaIndex`]: res[0],
      [`tabArray[${this.data.TabCur}].areaArray`]: res[1],
    })
  },  
  keywordChange(e) {
    this.data.tabArray[this.data.TabCur].keyword = e.detail.value;
  },
  arrangeChange(e) {
    this.setData({
      [`tabArray[${this.data.TabCur}].arrangeIndex`]: e.detail.value,
    })
  },

실행결과