how to render appendChild Js without duplicate

112 Views Asked by At

I am a new learning JS. Who can help me complete this code. I have 2 problem:

  • render child Node user Chat when click without duplicate

  • how to remove child Node user when close chat window

full code is here: Jsfiddle

// event handling when click
    handleEvents: function () {
        let _this = this;
        userChatList.onclick = function (e) {
            const userNode = e.target.closest(".user-chat__item");
            if (userNode) {
                userIndex = Number(userNode.getAttribute("user-num"));

                _this.renderUserChat(userIndex);

                const getChatWithItems = document.querySelectorAll(".chat-with__item");
                getChatWithItems.forEach(item => {
                    item.onclick = function(e){
                        const itemNode = e.target.closest(".chat-with__top i");
                        if(itemNode){
                            chatWithList.removeChild(chatWithItem);
                        }
                    }
                    
                }) 
            }

        }

    },

    //render user chat with someone
    renderUserChat: function (num) {
        // console.log(userIndex);
        chatWithItem = document.createElement("li");
        chatWithItem.classList.add("chat-with__item");
        chatWithItem.setAttribute('user-num', num);
        chatWithItem.innerHTML = `
                                <div class="chat-with__top">
                                    <div class="chat-with__img">
                                        <img src="${this.users[num].img}" alt="${this.users[num].name}">
                                        <span class="user__status ${this.users[num].status}"></span>
                                    </div>
                                    <p class="chat-with__name">${this.users[num].name}</p>
                                    <i class="fa-solid fa-xmark"></i>
                                </div>
                                <div class="chat-with__body">
                                <ul class="chat__text">
                                    <li class="chat-text__user">Hey. </li>
                                    <li class="chat-text__user user__chatting">I am here</li>
                                    <li class="chat-text__user user__chatting">What's going on?</li>
                                    <li class="chat-text__user">Have you finished the "project 2" yet?</li>
                                    <li class="chat-text__user user__chatting">I have been fixed bugs</li>
                                    <li class="chat-text__user">OK.</li>
                                </ul>
                                </div>
                                <div class="chat-width__footer">
                                    <i class="fa-solid fa-image"></i>
                                    <i class="fa-solid fa-folder"></i>
                                    <div class="chat-width__input">
                                        <input type="text" id="send-sms" name="send SMS" placeholder="...">
                                    </div>
                                    <i class="fa-solid fa-paper-plane-top"></i>
                                </div>
        `

        chatWithList.appendChild(chatWithItem);
    },
<ul class="chat-with__list">
</ul>

I have not still known how to solve it, up to now

2

There are 2 best solutions below

0
Mr Paul On BEST ANSWER

Finnaly I find the way to code. This is my way

handleEvents: function () {
    let _this = this;
    let currentChat = [];
    userChatList.onclick = function (e) {
        const userNode = e.target.closest(".user-chat__item");
        if (userNode) {
            userIndex = Number(userNode.getAttribute("user-num"));

            // get value 'userIndex' for currentChat array
            function getCurrentChat(arr, index) {
                arr.push(index);
            }

            // check value userIndex in a currentChat array
            function checkCurrentChat(arr, index) {
                if (arr.indexOf(index) < 0) {
                    getCurrentChat(currentChat, userIndex);
                    return true;
                } else {
                    return false;
                }
            }

            let isExisted = checkCurrentChat(currentChat, userIndex);

            // console.log(isExisted);
            if (isExisted) {

                _this.renderUserChat(userIndex);

            }

            const getChatWithItems = chatWithList.querySelectorAll(".chat-with__item");

            getChatWithItems.forEach( function(item) {
                item.onclick = function (e) {
                    const closeChat = e.target.closest(".chat-with__top i");
                    if(closeChat){
                        const getNum = Number(closeChat.parentElement.getAttribute("user-num"));
                        chatWithList.removeChild(item);
                        const findNum = currentChat.indexOf(getNum);
                        currentChat.splice(findNum, 1);
                    }
                }
            })

        }
    }


}

inside, i add an attribute to get number (userIndex):

<div class="chat-with__top" user-num ="${num}">

if you use second .parentElement, it will ok.

closeChat.parentElement.parentElement.getAttribute("user-num")
0
vanowm On

Just keep track which chat windows are opened in an object.

To give you basic idea of the concept:

// storage for opened chat windows
// this variable must be accessible by event handlers
const openedChats = {};

In chat opened event handler:

if (openedChats[userId]) //check if chat already opened
  return;

const chatWithItem = document.createElement("li");

...

openedChats[userId] = chatWithItem; //store window
chatWithList.appendChild(chatWithItem); //show window

In chat close event handler:

const chatWithItem = openedChats[userId]; // get opened chat

if (chatWithItem)
{
  chatWithItem.parentNode.removeChild(chatWithItem); // destroy window
  delete openedChats[userId]; // remove window
}

If you need to get list of all userIds that have opened chat windows, use:

const openedChatsIds = Object.keys(openedChats);