Çok düzeyli açılır liste nasıl oluşturulur ve sunucudan gelen verilerle nasıl bağlanır


15

Angular için çok yeniyim. Angular üzerinde biraz çalışmam var.

JsonRest Api çağırarak sunucudan gelen veriler için Yuvalanmış açılan listesini bağlamak gerekiyor .

Verilerin bir özniteliği vardır LgLevel, Grubun hiyerarşisindeki düzeyi belirtir. Ebeveyn level=0, Hemen Child=1, Grandchild=2vb. Childve hangi üst menünün, alt menünün orada olacağını gösteren bir alana Grandchildsahiptir ParentLocationGroup.

Bu benim jsonverilerim. Çok büyük verilerim var ama hepsini gösteremiyorum.

{
"ArrayOfLocationGroup": {
  "LocationGroup": [
     {
        "Id": "628",
        "Name": "TEST1",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources"
        },
        "ParentLocationGroup": {
           "_uuid": "bdce4396-9c60-4831-90f2-6f793becb362",
           "__text": "570"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "0"
        }
     },
     {
        "Id": "630",
        "Name": "TEST2",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "PAM-TEST"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     },
     {
        "Id": "631",
        "Name": "TEST3",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "PAA-TEST"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     },
     {
        "Id": "697",
        "Name": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "TEST4"
        },
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "PAE-TEST"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     },
     {
        "Id": "700",
        "Name": "TEST5",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "cuba"
        },
        "ParentLocationGroup": {
           "_uuid": "704af4cf-9feb-4f1b-aa00-d1c7926f7901",
           "__text": "694"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "2"
        }
     },
     {
        "Id": "706",
        "Name": "TEST5",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "VOIP-Test"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     },
     {
        "Id": "718",
        "Name": "TEST7",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     },
     {
        "Id": "719",
        "Name": "TEST8",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "MEM_RS"
        },
        "ParentLocationGroup": {
           "_uuid": "52073e2b-48b5-41a9-9c2b-d793835cf285",
           "__text": "718"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "2"
        }
     },
     {
        "Id": "752",
        "Name": "TEST9",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "ELDIT"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     },
     {
        "Id": "753",
        "Name": "TEST10",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "GXYA"
        },
        "ParentLocationGroup": {
           "_uuid": "52073e2b-48b5-41a9-9c2b-d793835cf285",
           "__text": "718"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "2"
        }
     },
     {
        "Id": "760",
        "Name": "TEST11",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "STAGE2"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     },
     {
        "Id": "761",
        "Name": "TEST12",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "INIT"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     },
     {
        "Id": "762",
        "Name": "TEST13",
        "GroupId": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "USIT"
        },
        "ParentLocationGroup": {
           "_uuid": "894055b6-b132-4dc2-a12a-971ecc0c7224",
           "__text": "628"
        },
        "LgLevel": {
           "_xmlns": "http://www.air-watch.com/servicemodel/resources",
           "__text": "1"
        }
     }
  ],
  "_xmlns:xsd": "http://www.w3.org/2001/XMLSchema"
}
}

Geliştirmek için denedim ama dosyada bootstrapstatik veri htmlve CSSbenim için karmaşık olan ayrı bir dosya ile tüm örnekleri bulundu .

Dinamik olarak kullanarak yapmak istiyorum TypeScript. Üzerinde çalışmaya nasıl başlayabilirim.


İlk olarak, veri biçimi XMLdeğil JSON. Denediğiniz her şeyi de ekleyebilir misiniz? Belki daha ayrıntılı olarak benimsediğiniz yaklaşım.
vatz88

@ vatz88 - Evet bu sadece postacıdan yapıştırılan xml. htmlStatik iç içe listeleri olan kodu denedim . Düzenlemeye çalışacağım ve Jsonveri göndereceğim . Ne denediğimi
sevmeyeceksin

Şimdiye kadar kodladığınız şeyi endişelendirmenize gerek yok. Yaklaşım - ts dosyasındaki verileri sabit kodlamak, html'de açılır listeyi oluşturmak için ihtiyacınız olan verilere göre bağlamalar yapmak olacaktır. Bu mantık doğru olduğunda, verileri dinamik olarak elde etmeye çalışın ve ardından bağlamanın açısal olarak sihri yapmasına izin verin.
vatz88

@ vatz88 - Statik kodum dosyadaydı html. Başlamak için bir fikrim var. Bana yardım edebilirsin.
Arvind Chourasiya

@ ArvindChourasiya LgLevel 1'in birçok çocuğu var, LgLevel 2'nin hangi torununun hangi çocuğa ait olduğunu nasıl belirleyebilirim?
Satish Pai

Yanıtlar:


4

Bu, json verilerinizden iç içe geçmiş verilere göre ihtiyacınız olan bir kodlama örneğidir. Şimdi model verilerini kullanarak DOM'da biçimlendirilmiş json verilerini döngüye alabilirsiniz . Umarım bu çok seviyeli bir açılır liste oluşturmanıza yardımcı olur

groupBy(xs, key) {
   return xs.reduce(function (rv, x) {
     (rv[x[key]] = rv[x[key]] || []).push(x);
    return rv;
   }, {});
 }

var model;

getData() {
 var   sampleData = {
  "ArrayOfLocationGroup": {
    "LocationGroup": [
      ...
      ...//Server response data
      ],
    "_xmlns:xsd": "http://www.w3.org/2001/XMLSchema"
  }
 }    

var list = this.sampleData["ArrayOfLocationGroup"]["LocationGroup"];
var formattedList = [];

list.forEach(element => {

  var obj = {  //Make sure your server response data to like this structure
    "Id": element.Id,
    "Name": element.Name,
    "GroupId": element.GroupId.__text,
    "ParentLocationGroup": element.ParentLocationGroup.__text,
    "LgLevel": element.LgLevel.__text,
    "Child" : []
  }
  formattedList.push(obj);
});

var groupDataList = this.groupBy(formattedList, "LgLevel");

var parents = groupDataList[0];
var child = groupDataList[1];
var childOfChild = groupDataList[2];

child.forEach(c => {
  c.Child = childOfChild.filter(x => x.ParentLocationGroup == c.Id);
})

parents.forEach(p => {
  p.Child = child.filter(x => x.ParentLocationGroup == p.Id);
})

this.model = parents;
}

Html Dosyası

    <ul class="nav site-nav">
     <li class=flyout>
      <a href=#>Dropdown</a>
      <!-- Flyout -->
      <ul class="flyout-content nav stacked">
        <li *ngFor="let parent of model" [class.flyout-alt]="parent.Child.length > 0"><a href=#>{{parent.Name}}</a>
          <ul *ngIf="parent.Child.length > 0" class="flyout-content nav stacked">
            <li *ngFor="let c of parent.Child" [class.flyout-alt]="c.Child.length > 0"><a href=#>{{c.Name}}</a>
              <ul *ngIf="c.Child.length > 0" class="flyout-content nav stacked">
                <li *ngFor="let cc of c.Child" [class.flyout-alt]="cc.Child.length > 0"><a href=#>{{cc.Name}}</a></li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>

Sunucu yanıt verilerinize göre model verilerini düzenleyin. Yanıt json biçimi değiştirildi ( __text - #text )

 var obj = {
    "Id": element.Id,
    "Name": element.Name && element.Name.#text ? element.Name.#text : element.Name,
    "GroupId": element.GroupId && element.GroupId.#text ? element.GroupId.#text : element.GroupId,
    "ParentLocationGroup": element.ParentLocationGroup && element.ParentLocationGroup.#text ? element.ParentLocationGroup.#text : element.ParentLocationGroup,
    "LgLevel": element.LgLevel && element.LgLevel.#text ? element.LgLevel.#text : element.LgLevel,
    "Child" : []
  }

.Html dosyasını da gönderebilir misiniz?
Arvind Chourasiya

@ArvindChourasiya Do etiket açılan ya da sadece açılır (seçmesi gerekmektedir linki )?
Yaseer

Yukarıdaki bağlantıdan dolor seçeneğinde görünmesi gerekiyor.
Arvind Chourasiya

@ArvindChourasiya ben html ile yayınını güncelledi
Yaseer

Kodunla biraz kafam karıştı. Hiçbir getDatayerde kullanmıyorsunuz . Lütfen kodunuzu kontrol edip açılış ve kapanışlar ekleyebilir misiniz?
Arvind Chourasiya

4

Görünüşe göre gereksinimlerinizi karşılayan başka bir cevabınız var. Ama bu çözüm bir ara gelmemi sağladı. Bu yüzden yine de göndermeye karar verdim.

Aşağıdaki kod snippet'i, üst-alt hiyerarşik verinin ağaç benzeri yapısını oluşturmak için kullanılır:

  processData(data) {
    let locationData = data.ArrayOfLocationGroup.LocationGroup;
    let level0 = [];
    let tempMap = {};
    for (let i = 0; i < locationData.length; i++) {
      let currItem = this.getDataObject(locationData[i]);
      if (tempMap[currItem.id] == undefined) {
        tempMap[currItem.id] = currItem;
        if (tempMap[currItem.parentLocationGroup] == undefined) {
          tempMap[currItem.parentLocationGroup] = { children: [] };
        }
        tempMap[currItem.parentLocationGroup].children.push(currItem);
      } else {
        if (tempMap[currItem.id]) {
          currItem.children = tempMap[currItem.id].children;
        }
        tempMap[currItem.id] = currItem;
        if (tempMap[currItem.parentLocationGroup] == undefined) {
          tempMap[currItem.parentLocationGroup] = { children: [] };
        }
        tempMap[currItem.parentLocationGroup].children.push(currItem);
      }
      if (currItem.lgLevel == "0") {
        if (level0.indexOf(currItem) == -1) {
          level0.push(currItem);
        }
      }
    }
    this.levelData = level0;
  }

Toplanan veriler, dropdownçok düzeyli açılır menü olarak işlev gören bir bileşene girdi olarak iletilir .

Bu çözümün her seviyedeki çocuk için işe yarayacağı düşünülmektedir. dropdownBileşen veri ihtiyaçlarına göre oluşturulur şeklini değiştirmek için değiştirilebilir.

Ben aldı htmlve cssburadan düzeyli açılır menüden için:
https://phppot.com/css/multilevel-dropdown-menu-with-pure-css/
: Bu cevaptan dışında tıklandığında kod menü açılır listesini kapatmak için
https: //stackoverflow.com/a/59234391/9262488

Umarım bunu faydalı bulursun.


Kodunuzu kontrol ettim. İşe yarıyor. Yanıt gönderdiğiniz için teşekkür ederiz. Bana verilerimi nasıl aldığınızı söyler misiniz? http isteği için (mocky.io).
Arvind Chourasiya

Mocky sahte dinlenme api oluşturmak için çevrimiçi bir araçtır. Gönderdiğiniz verileri aldım ve mocky kullanarak bir dinlenme API'si oluşturmak için kullandım.
NiK648

1

Neden bir ağaç bileşeni oluşturup girdileri özyinelemeli olarak bağlama?

Önerilen çözüm

  • derinlemesine agnostik - veri ağacınızdaki herhangi bir sayıda seviye için çalışır (geçici olarak değişse bile)
  • oldukça verimli - verilerinizi toplar O(n).

İlk olarak veri modelini tasarlayın - bir ağaç düğümü yapısı olmalıdır:

export interface GroupId { /* appropriate members... */ }

export interface ParentLocationGroup { /* other members... */ __text: string; }

export interface LgLevel { /* other members... */ __text: string; }

export interface DataModel {
  Id: string,
  Name: string,
  GroupId: GroupId,
  ParentLocationGroup: ParentLocationGroup,
  LgLevel: LgLevel,
  children: DataModel[]
}

Ardından verilerinizi üst düzey bileşende (veya daha da iyisi - veri hizmetinizde toplayın; bunu yeterince kolayca özetleyebilmelisiniz):

// dropdown.component.ts

@Component({
  selector: 'app-dropdown',
  template: `
    <ul class="nav site-nav">
      <li class=flyout>
        <a href=#>Dropdown</a>
        <app-dynamic-flyout [data]="data"></app-dynamic-flyout>
      </li>
    </ul>
  `
})
export class DropdownComponent {

  data: DataModel[];

  constructor(dataService: YourDataService){

    let data;
    dataService.getYourData()
      .pipe(map(d => d.ArrayOfLocationGroup.LocationGroup)))
      // Make sure every item has the `children` array property initialized
      // since it does not come with your data
      .subscribe(d => data = d.map(i => ({...i, children: []})));

    // Create a lookup map for building the data tree
    let idMap = data.reduce((acc, curr) => ({...acc, [curr.Id]: curr}), {});
    this.data = data.reduce(
      (acc, curr) => curr.LgLevel.__text == 0 || !curr.ParentLocationGroup
        // Either the level is 0 or there is no parent group
        // (the logic is unclear here - even some of your lvl 0 nodes have a `ParentGroup`)
        // -> we assume this is a top-level node and put it to the accumulator
        ? [...acc, curr]
        // Otherwise push this node to an appropriate `children` array
        // and return the current accumulator
        : idMap[curr.ParentLocationGroup.__text].children.push(curr) && acc, 
      []
    );
  }
}

Ve tekrarlayan dinamik açılır pencere bileşenini oluşturun:

// dynamic-flyout.component.ts

@Component({
  selector: 'app-dynamic-flyout',
  template: `
    <ul *ngIf="!!data.length" class="flyout-content nav stacked">
      <li *ngFor="let item of data" [class.flyout-alt]="!!item.children.length">
        <a href=#>{{item.Name}}</a>
        <app-dynamic-flyout [data]="item.children"></app-dynamic-flyout>
      </li>
    </ul>
  `
})
export class DynamicFlyoutComponent {
  @Input() data: DataModel[];
}

Çözüm test edilmedi ancak sizi doğru yönde gösterecektir ...

Umarım bu biraz yardımcı olur :-)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.