[Fixed] Angular 5 nested dynamic subcategory does not work correctly

Issue

I’m working on angular 5 and django rest as backend the datas is comming from my server im trying to show sub category of my category next to it parent .by this code last subcategory will show top of its parent always. also subcategory ul will repeat twice.. i spend much time but i cant fix it … anyone know how can i fix this issue?

public hoveredCategory: any;
public hoveredsCategory: any;

ngOnInit() {

    this.datas = [
    {
        "id": 12,
        "parent_id": null,
        "title": "develop"
    },
    {
        "id": 13,
        "parent_id": null,
        "title": "business"
    },
    {
        "id": 14,
        "parent_id": 12,
        "title": "web"
    },
    {
        "id": 16,
        "parent_id": 14,
        "title": "php"
    },
    {
        "id": 17,
        "parent_id": 14,
        "title": "asp"
    },
    {
        "id": 18,
        "parent_id": 12,
        "title": "android"
    },
    {
        "id": 19,
        "parent_id": 18,
        "title": "java"
    },
    {
        "id": 20,
        "parent_id": 13,
        "title": "speach"
    },
    {
        "id": 21,
        "parent_id": 20,
        "title": "full"
    },
    {
        "id": 22,
        "parent_id": 20,
        "title": "mini"
    },
    {
        "id": 23,
        "parent_id": 13,
        "title": "no speach"
    },
    {
        "id": 24,
        "parent_id": 14,
        "title": "html"
    },
    {
        "id": 25,
        "parent_id": 23,
        "title": "nospech2"
    }
]

      this.categories = this.datas.filter(c => c.parent_id === null).map(title => <{ title: string, sub: any, subsub: object[] }> {
        title: title.title,
        sub: this.datas.filter(sc => sc.parent_id === title.id)
          .map(sc => <{ title: string, sub: any }> {
            title: sc.title,
            sub: this.datas.filter(c => c.parent_id !== null && sc.id === c.parent_id).map(ss => <{ secondSub: object[] }> {secondSub: ss.title})
          }),

      });
  hover(event, category) {
    this.hoveredCategory = category;    
  }

  hoversc(event, category) {
    this.hoveredsCategory = category;
  }

html:

<ul id='menu' class="right">
  <li><a class='prett' href='#' title='Menu'><span id="cat" class="ion-android-apps"></span></a>
    <ul class='menus'>
      <li class='has-submenu' *ngFor="let cat of categories">
        <a class='prett' href='#'
           (mouseover)="hover($event, cat)">{{ cat.title }}
        </a>
        <ul class='submenu'>
          <li>
            <a href="#" title="Sub Menu" *ngFor="let sc of hoveredCategory?.sub" (mouseover)="hoversc($event, sc.sub)">{{ sc.title }}</a>
            <ul class='subsubmenu'>
              <li *ngFor="let ssc of hoveredsCategory">
                <a href="#" title="Sub Menu">{{ ssc.secondSub }}</a>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

css code:

#menu {
  position: relative;
  margin-right: 80px;
  top: 18px;
  border: none;
}

#menu ul,
#menu li {
  margin: 0 0;
  padding: 0 0;
  list-style: none
}

#menu ul {
  height: 35px
}

#menu li {
  float: left;
  display: inline;
  position: relative;
}

#menu li:first-child {
  border-left: none
}

#menu a {
  display: block;
  line-height: 35px;
  padding: 0 14px;
  text-decoration: none;
  color: #007791;
}

#menu li:hover > a,
#menu li a:hover {
  background: #fff;
}

#menu input {
  display: none;
  margin: 0 0;
  padding: 0 0;
  width: 80px;
  height: 35px;
  opacity: 0;
  cursor: pointer
}

#menu label {
  font: bold 30px Arial;
  display: none;
  width: 35px;
  height: 36px;
  line-height: 36px;
  text-align: center
}

#menu label span {
  font-size: 12px;
  position: absolute;
  left: 35px
}

#menu ul.menus {
  height: auto;
  width: 180px;
  background: #fff;
  position: absolute;
  z-index: 99;
  display: none;
  border: 0;
}

#menu ul.menus li {
  display: block;
  width: 100%;
  text-transform: none;
}

#menu li:hover ul.menus {
  display: block
}

#menu a.home {
  background: #c00;
}

#menu a.prett {
  padding: 0 27px 0 14px
}

#menu a.prett::after {
  content: "";
  width: 0;
  height: 0;
  border-width: 6px 5px;
  border-style: solid;
  border-color: #eee transparent transparent transparent;
  position: absolute;
  top: 15px;
  right: 9px
}

#menu ul.menus a:hover {
  background: #f2f3f5;
}

#menu ul.menus .submenu {
  display: none;
  position: absolute;
  left: 180px;
  background: #fff;
  top: 0;
  width: 120px;
  height: auto;
}

#menu ul.menus .subsubmenu {
  display: block;
  position: absolute;
  left: 100%;
  background: #fff;
  top: 0;
  height: auto;
  width: 120px;
}

#menu ul.menus .submenu li {
}

#menu ul.menus .has-submenu:hover .submenu {
  display: block;
}

#menu ul.menus .has-submenu .submenu:hover .subsubmenu {
  display: block;
}

Solution

hoveredsCategory value doesn’t cleaned. So when hover events occurs in different category old hoveredsCategory is preserved. So restore hoveredsCategory on hover:

 hover(event, category) {
  //  console.log('hover', category)
    this.hoveredCategory = category;
    this.hoveredsCategory = null;
  }

StackBlitz EXAMPLE

Leave a Reply

(*) Required, Your email will not be published