중복 컨텐츠를 보여주는 메뉴 만들기

ahncheer·2023년 7월 7일
0

LWC & LWR

목록 보기
34/45

1. 메뉴에 맞는 리스트를 새로 만들어 저장하고, 새로운 리스트를 화면에 보여주는 방식

1-1) JS

@track menuList = [
    {name : '메뉴1', value : 'a01', checked : true},
    {name : '메뉴2', value : 'a02', checked : false},
    {name : '메뉴3', value : 'a03', checked : false},
    {name : '메뉴4', value : 'a04', checked : false},
    {name : '메뉴5', value : 'a05', checked : false},
];

@track defaultList = [
    {name : '이름1', content : '내용1', filter : ['a01']},
    {name : '이름2', content : '내용2', filter : ['a01', 'a02']},
    {name : '이름3', content : '내용3', filter : ['a01', 'a02', 'a03']},
    {name : '이름4', content : '내용4', filter : ['a01', 'a02', 'a04']},
    {name : '이름5', content : '내용5', filter : ['a01', 'a02', 'a05']},
];
@track contentList = this.defaultList;

getRadioValue(e){
    let idx = e.target.dataset.value;
    console.log('▷ idx : ', idx);
    this.setList(idx);
}

// 리스트 필터해서 다시 배열
// (보통 이 부분은 프론트가 필터링 하지 않고, apex개발자 분께서 필터링 해서 새로운 리스트를 주십니다.)
setList(radioIdx){
    console.log('▷ setList - radioIdx : ', radioIdx);
    let newList = [];
    this.defaultList.forEach((el, index) => {
        if(el.filter.findIndex((x) => x === radioIdx) > -1){
            newList.push(el);
        }
    });
    console.log('▶ newList : ', newList);
    this.contentList = newList;
}

1-2) HTML

<div class="test-area">
    <!-- 메뉴 -->
    <ul class="test-menu">
    <template for:each={menuList} for:item="item" for:index="idx">
        <li key={item.value} data-value={item.value} onclick={getRadioValue}>
            {item.name} !
        </li>
        
    </template>
    </ul>
    <!-- 내용 -->
    <div class="test-content">
    <template for:each={contentList} for:item="item" for:index="idx">
        <div key={item.value} class="slds-box content-list" >
            <p>{item.name} - {item.content}</p>
        </div>
    </template>
    </div>

</div>

1-3) CSS


.test-area{
    width: 800px;
    background-color: #f7f8f5;
    margin: 0 auto 300px;
    padding: 20px;
}
.test-menu {
    display: flex;
    justify-content: center;
    gap: 20px;
}

.test-menu li{
    padding: 5px;
    color: #282828;
    background-color: beige;
    border: 1px solid #bdbd83;
    border-radius: 5px;
    cursor: pointer;
}
.test-menu li:hover{
    background-color: #616148;
    border-color: #616148;
    color: #FFF;
}
.test-content{
    margin-top: 20px;
    display: grid;
    gap: 20px;
    grid-template-columns: 1fr 1fr 1fr;
}
.test-content div{
    background-color: #FFF;
    height: 100px;
}

1-4) 화면 확인

+ data-value 대신 data-index값 사용하기


현재 코드로는 value값이 고스란히 html에 보이고 있기 때문에, index값을 받아와 List의 index번째의 value값을 받아오도록 수정

바뀐 부분만 드래그 해서 스샷으로 찍었습니다.

2. 선택한 메뉴에 해당하지 않는 컨텐츠만 Class를 넣어서 숨김 처리하기

2-1) HTML


1의 코드에서 달라진 부분만 드래그 했습니다.

2-2) JS

@track menuList = [
    {name : '메뉴1', value : 'a01', checked : true},
    {name : '메뉴2', value : 'a02', checked : false},
    {name : '메뉴3', value : 'a03', checked : false},
    {name : '메뉴4', value : 'a04', checked : false},
    {name : '메뉴5', value : 'a05', checked : false},
];

@track defaultList = [
    {name : '이름1', content : '내용1', filter : 'a01'},
    {name : '이름2', content : '내용2', filter : 'a01a02'},
    {name : '이름3', content : '내용3', filter : 'a01a02a03'},
    {name : '이름4', content : '내용4', filter : 'a01a02a04'},
    {name : '이름5', content : '내용5', filter : 'a01a02a05'},
];
@track contentList = this.defaultList;

getRadioValue(e){
    let idx = e.target.dataset.index;
    let selectedValue = this.menuList[idx].value;
    console.log('▷ idx : ', selectedValue);
    this.setListHide(selectedValue);
}

//리스트 중 일부를 숨기기, slds-assistive-text는 안보이게 하는 class이름입니다.
setListHide(radioIdx){
    let contentArea = this.template.querySelectorAll('.slds-box.content-list');
    console.log('▷ contentArea : ', contentArea);

    contentArea.forEach((el, index) => {
        let dataName = el.dataset.name;
        // console.log('dataName : ', dataName);
        if(dataName.indexOf(radioIdx) > -1){
            el.classList.remove('slds-assistive-text');
        }else{
            el.classList.add('slds-assistive-text');
        }
    }); 
}

setListHide 추가, defaultList의 filter를 문자열로 변경

2-3) CSS

1-3과 동일

2-4) 화면 확인


기능은 정상적으로 동작합니다. 그러나 data-name에 value값이 보이는 것이 안타깝습니다.

3. 2에서 index값만 받아 처리해보기

기존 List와 비교해 값이 없는 index를 찾고, 리스트 중 index번째 컨텐츠를 숨기기

3-1) HTML

3-2) JS

@track menuList = [
    {name : '메뉴1', value : 'a01', checked : true},
    {name : '메뉴2', value : 'a02', checked : false},
    {name : '메뉴3', value : 'a03', checked : false},
    {name : '메뉴4', value : 'a04', checked : false},
    {name : '메뉴5', value : 'a05', checked : false},
];

@track defaultList = [
    {name : '이름1', content : '내용1', filter : ['a01']},
    {name : '이름2', content : '내용2', filter : ['a01', 'a02']},
    {name : '이름3', content : '내용3', filter : ['a01', 'a02', 'a03']},
    {name : '이름4', content : '내용4', filter : ['a01', 'a02', 'a04']},
    {name : '이름5', content : '내용5', filter : ['a01', 'a02', 'a05']},
];

getRadioValue(e){
    let idx = e.target.dataset.index;
    let selectedValue = this.menuList[idx].value;
    console.log('▷ idx : ', selectedValue);
    this.setListHide(selectedValue);
}

// 기존 List와 비교해 값이 없는 index를 찾고, 리스트 중 index번째 컨텐츠를 숨기기
// slds-assistive-text는 안보이게 하는 class이름입니다.
setListHide(selectedValue){
    let contentArea = this.template.querySelectorAll('.slds-box.content-list');
    console.log('▷ contentArea : ', contentArea);

    this.defaultList.forEach((el, index) => {
        if(el.filter.findIndex((x) => x === selectedValue) > -1){
            contentArea[index].classList.remove('slds-assistive-text');
        }else{
            contentArea[index].classList.add('slds-assistive-text');
        }
    }); 
}

3-3) 결과 확인


data-name이나 value값이 HTML에 표시되지 않습니다.

4. checked true인 경우에만 CSS 추가하기

다 만들고 보니 checked라는 속성은 추가해두고, 사용하지 않은 것을 발견해서 급하게 추가했습니다.
데이터를 수정하는 방식입니다. 데이터를 수정하지 않고 class를 변경하는법 -> lwc 에서 class 변경하기

4-1) JS


바뀐 값을 바로 적용할 수 있도록 get을 사용

index를 비교해서 클릭한 index만 true, 다른 것의checked는 false가 되도록 수정

4-2) HTML


메뉴에 data-check라는 속성 추가

4-3) CSS

[data-check='true']인 경우 배경색과 글씨색이 다르게 되도록 수정

4-4) 화면 확인

profile
개인 공부 기록용.

1개의 댓글

comment-user-thumbnail
2023년 7월 7일

GIF는 ScreenToGif를 사용했습니다

답글 달기