lundi 6 juin 2022

How to Efficiently Utilize Objects in Conjunction with HTML Elements

I am getting pretty deep into an employee talent management system website and I am finding out really quick why OOP is so talked about. Being able to efficiently utilize it would change that game for me and make my codebase much more maintainable. I am currently working on a dropdown menu section, and while I have implemented OOP, I can tell from a mile away it is not "good code." It gets the job done but is very messy. I will have an example of the Object and Implementation down below. I have tried watching a few videos on implementing OOP in an existing project, but I keep coming up dry. I understand the basic concepts, but I am not sure how to implement these ideas in a real world application.

Here are some sticking points I am having:

  1. I am not confident I instantiated my objects correctly/efficiently. I have a list of toggleable menus, each representing a candidate in the portal. Well, I created an object for each menu using a for loop. This worked, but it felt unintuitive. When I wanted to attach click events to these menus, I had to loop through them a second time to attached to objects methods as click events.

  2. I felt I had a lot of 'if' statements in my Object. This is because I see myself using the object again in the future, but I do not think each menu will have all the same features. For example, this specific menu had a fade in animation when clicked. But, I doubt every toggleable menu will have this feature. I don't know, I just felt it made the code way more difficult to navigate.

  3. I did not like having to loop through my menu elements and attach methods as click events. This made me have to run an additional for loop and felt 'off'. I was tempted to handle all the event attachments inside the object itself, but I wasn't sure if this is bad practice. It seemed like a good idea and would save a lot of code, but I'm not sure.

Long story short, I can see myself using OOP for forms, buttons, toggleable menus, navbars, (ect.) all over the place. The problem is I am not sure how to actually carry out the process of handling HTML elements and converting them to Objects in a clear and concise manner.

I looked into some design patterns on refactoring.guru, but I felt these concepts were past the scope of what I am trying to do. They all felt like more advanced concepts to take on after getting a solid grip on objects. It was helpful and I really liked the builder pattern. I am currently working on a branch which implements the builder pattern into my current scenario.

Any thoughts, advice, or direction?

Here is an example of the Object and it's Implementation:

TOGGLE MENU OBJECT

class ToggleMenu {
    constructor(wrapper, menu, openIcon, closeIcon, title, hiddenMenu) {
        this.wrapper = wrapper
        this.menu = menu
        this.openIcon = openIcon
        this.closeIcon = closeIcon
        this.title = title
        this.hiddenMenu = hiddenMenu
        this.toggled = false
    }
    props() {
        console.log(this.menu)
        console.log(this.openIcon)
        console.log(this.closeIcon)
        console.log(this.title)
        console.log(this.hiddenMenu)
        console.log(this.toggled)
    }
    openHiddenMenu(config) {
        if (config == undefined){
            config = {}
        }
        if (config.menuBackGroundColor !== undefined){
            this.menu.style.backgroundColor = config.menuBackGroundColor
        }
        if (config.titleColor !== undefined){
            this.title.style.color = config.titleColor
        }
        if (config.hiddenMenuDisplay !== undefined){
            this.hiddenMenu.style.display = config.hiddenMenuDisplay
        }
        if (config.hiddenMenuAnimation !== undefined){
            this.hiddenMenu.style.animationName = config.hiddenMenuAnimation
        }
        if(config.menuAnimation !== undefined){
            this.menu.style.animationName = config.menuAnimation
        }
        this.openIcon.style.display = 'none'
        this.closeIcon.style.display = 'block'
        this.toggled = true
    }
    closeHiddenMenu(config){
        if (config == undefined){
            config = {}
        }
        if (config.menuAnimation !== undefined && this.toggled == true){
            this.menu.style.animationName = config.menuAnimation
        }
        this.menu.style.backgroundColor = ''
        this.openIcon.style.display = ''
        this.closeIcon.style.display = ''
        this.title.style.color = ''
        this.hiddenMenu.style.display = ''
        this.toggled = false
    }
}

IMPLEMENTATION

const initCandidateMenus = () => {
    let candidateToggleMenus = document.getElementsByClassName('candidate-toggle-menu')
    let candidateToggleWrappers = document.getElementsByClassName('candidate-toggle-menu-wrapper')
    let hiddenMenus = document.getElementsByClassName('hidden-candidate-menu')
    let toggleMenus = []
    //collecting toggle menu objects
    for (x = 0; x < candidateToggleMenus.length; x++){
        let toggleMenu = new ToggleMenu(
            candidateToggleWrappers[x],
            candidateToggleMenus[x],
            candidateToggleMenus[x].getElementsByClassName('candidate-open-icon')[0],
            candidateToggleMenus[x].getElementsByClassName('candidate-close-icon')[0],
            candidateToggleMenus[x].getElementsByClassName('candidate-name')[0],
            hiddenMenus[x],
        )
        toggleMenus.push(toggleMenu)
    }
    //looping through toggle menu objects
    for (x = 0; x < toggleMenus.length; x++){
        let currentMenu = toggleMenus[x]
        currentMenu.openIcon.addEventListener('click', () => {
            //closing all other toggle menus
            for (y = 0; y < toggleMenus.length; y++){
                toggleMenus[y].closeHiddenMenu()
            }
            //opening current menu
            currentMenu.openHiddenMenu({
                menuBackGroundColor: 'var(--main-clr)',
                titleColor: 'var(--white)',
                menuAnimation: 'fade-title-color',
                hiddenMenuDisplay: 'flex',
                hiddenMenuAnimation: 'open-hidden-menu'
            })
        })
        currentMenu.closeIcon.addEventListener('click', () => {
                //closing current menu
                currentMenu.closeHiddenMenu()
        })
    }
}

Aucun commentaire:

Enregistrer un commentaire