Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

angular - Angular2 nested *ngFor

I use an array to store a list of group objects and an array of a list of light objects. I want to show the first group in the html and all connected lights to that group. After that the next group and the related lights and so on....

<div>
  <ul>
    <li *ngFor="let group of hueGroups">
      {{group.name}}
      <li *ngFor="let light of hueLights; let i = index">
      {{hueLights[group.lights[i]].name}}
    </li>
  </ul>
</div>



export class AppComponent implements OnInit {
  hueGroups:any[];
  hueLights:any[];

  constructor(){
    this.hueGroups = [];
    this.hueLights = [];
  }

  listAllGroups(){
   for(var g in MyHue.Groups){ //MyHue.Groups returen an array with objects
    console.log(g);
    console.log(MyHue.Groups[g].name);
    for(var id:number = 0; id < MyHue.Groups[g].lights.length; id++){
      console.log("LightID:" + MyHue.Lights[MyHue.Groups[g].lights[id]].name); // Returns the name of the Lights
    }
    this.hueGroups.push(MyHue.Groups[g]);
  }

  listAllLights(){
   for(var l in MyHue.Lights){ //MyHue.Lights returns an array with objects
    console.log(MyHue.Lights[l]);
    this.hueLights.push(MyHue.Lights[l]);
   }
  }

}

If I try to run this I get the error

Cannot read property 'lights' of undefined

So I think the syntax is wrong for the nested ngFor. It should be possible to call "group" from above.

EDIT: This is the important part of how an object of the MyHue.Groups looks like:

{action:Object
 class:"Living room"
 lights: Array(2)
   0:"3"
   1:"1"
 name:"Room1"}

In the Group object there is only the ID of the lights which are depending to this group

This is the important part of how a light object looks like:

 {state: Object, type: "Extended color light", name: "Couch1", modelid: "LCT007"…}

This is what I get if I print the hole array to the console:

Object {1: Object, 3: Object, 4: Object}

So I have to match which Light ID is in which Group, then check the light Object for the name

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Looks like you need to create a simpler data structure where your light objects are contained in an array property of your hueGroup objects. Then you'll be able to iterate easily through your groups, and each of their lights in your template.

For example, your template should look more like this:

<ul>
    <li *ngFor="let group of hueGroups">
    {{group.name}}
    <ul>
        <li *ngFor="let light of group.lights">
        {{light.name}}
        </li>
    </ul>
    </li>
</ul>

And your component should contain a hueGroups data object or model to render.

hueGroups = [{
    name: "group 1",
    lights: [{
      name: "light 1"
    },{
      name: "light 2"
    }]
  },
  {
    name: "group 2",
    lights: [{
      name: "light 3"
    },{
      name: "light 4"
    }]
  }];

Check out this plunker for a working example of what I mean: http://plnkr.co/edit/THXdN8zyy4aQMoo4aeto?p=preview

The key here is using your template to reflect the content of the component's data that's backing it. Beyond my example, you might want to use typescript to define an interface or class for your groups and lights.

Your example is a little more complicated because your template is trying to render a synthesis of two data structures (your hueGroup.lights seem to be arrays of just light ids). I'd recommend making a function that creates a hueGroup object with embedded light objects your template can iterate over easily. Here's an example of such a function:

Updated to reflect the example data:

ngOnInit(){
    this.hueGroups = this.hueGroupSource.map((group)=>{
      let lightObjects = group.lights.map((lightID)=>{
        return this.hueLightsSource.find((light, index) => {return index === lightID});
    });
    group.lights = lightObjects;
    return group;
  });

}

Here is a plunker showing it in a working example. http://plnkr.co/edit/V309ULE8f6rCCCx1ICys?p=preview


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...