How can I create an ion-list with header using firebase?


#1

Hi, I have a question, in the attach image can you see the ion-list with header,

image

I see this code, but I don’t know how can i create a Header “member”

My information is like this

asignature has ID, data, member

ID data member
1 Pen Office
2 Sheet Office
2 Crayola Office
4 water Kitchen

How can I put in the header Office, without repeat Office 2 times using firebase.

{{asignature.member}} {{asignature.data}}

Can you help me?


#2

Can’t speak to Firebase, but there are a zillion ways of doing this in vanilla Angular. One:

let blended: Thing[] = [];
let prevgroup;
for (let i = 0; i < things.length; ++i) {
  if (things[i].member !== prevgroup) {
    blended.push({data: things[i].member, isGroup: true});
  }
  blended.push(things[i]);
  prevgroup = things[i].member;
}
<ion-list>
<ng-container *ngFor="let thing of blended">
<ion-list-header *ngIf="thing.isGroup">{{thing.data}}</ion-list-header>
<ion-item *ngIf="!thing.isGroup">{{thing.data}}</ion-item>
</ng-container>
</ion-list>

#3

I receive a Json like this in file.ts

{
	"001": {
		"ID": "1",
		"data": "Pen",
		"member": "Office"
	},
	"002": {
		"ID": "2",
		"data": "Sheet",
		"member": "Office"
	},
	"003": {
		"ID": "3",
		"data": "Crayola",
		"member": "Office"
	},
	"004": {
		"ID": "4",
		"data": "Water",
		"member": "Kitchen"
	},
	"005": {
		"ID": "5",
		"data": "Other",
		"member": "Other"
	}
}

In my html

<ion-list>
  <ion-list-header *ngFor="let asignature of asignatures">
      {{asignature.member}}
  </ion-list-header>
  <button ion-item *ngFor="let asignature of asignatures">
      {{asignature.data}}
  </button>  
  </ion-list>
  <div padding>
      <button ion-button block (click)="createAsignatura()">Create item</button>
  </div>

All night i was searching a clue.

Can you helpme?


#4

I found this, but doesn’t works

<ion-content padding>
  <ion-list>
    <ion-item-group *ngFor="let group of asignatures">
      <ion-item-divider color="secondary">{{group.member}}</ion-item-divider>
        <button *ngFor="let element of group.data" ion-item >
        {{element.data}}
        </button>
    </ion-item-group>
  </ion-list>
</ion-content>

wich is my error?
Cannot find a differ supporting object ‘Pen’ of type ‘string’. NgFor only supports binding to Iterables such as Arrays.


#5

Your json is not valid json.

See: https://google.github.io/styleguide/jsoncstyleguide.xml


#6

This is my json

{
	"001": {
		"ID": "1",
		"data": "Pen",
		"member": "Office"
	},
	"002": {
		"ID": "2",
		"data": "Sheet",
		"member": "Office"
	},
	"003": {
		"ID": "3",
		"data": "Crayola",
		"member": "Office"
	},
	"004": {
		"ID": "4",
		"data": "Water",
		"member": "Kitchen"
	},
	"005": {
		"ID": "5",
		"data": "Other",
		"member": "Other"
	}
}

#7

Looks valid now.

You can use: https://jsonformatter.org/ to validate your json.

I would suggest you use "id" and not "ID".


#8

Thanks, the problem isnt the ID, the problem is not accept the grouping in ion-item-group.

Do you have any suggest?


#9

Convert your object to an array and then you can iterate through it. Maybe Object.items()?


#10

I use Google Hosting and Firestore (angularfire2/firestore) so my Services return an Observable:

  public listBeers(venueId: string): Observable<Beer[]>  {

    this.beers = this.afs.collection('venues').doc(venueId).collection('beers', ref => ref.orderBy('name', 'asc'));
    return this.beers.snapshotChanges().map(actions => {
      return actions.map(a => {
        const data = a.payload.doc.data() as Beer;
        const id = a.payload.doc.id;
        return { id, ...data };
      });
    });
  }

Which my Page’s subscribe to:

  ...

  public item: Venue;
  public beers: Array<Beer>;

  constructor(public navCtrl: NavController,
              public navParams: NavParams,
              private venuesService: VenuesService,
              private logger: LoggerService) {

    this.item = navParams.get('item');
  }

  public ionViewDidLoad() {

    this.venuesService.listBeers(this.item.id).subscribe(data => {
      this.beers = data;
    });
  }

And, render:


<ion-content>

  <ion-card>

    ...

  </ion-card>

  <ion-list>

    <div *ngFor="let beer of beers; first as isFirst">

      <ion-item-divider *ngIf="isFirst && isValidMenu(item, 'Just Arrived')" color="light">
        Just Arrived
      </ion-item-divider>

      <button ion-item *ngIf="isValidMenuItem(beer, 'Just Arrived')" (click)="openPage(beer)">

        ...

      </button>

    </div>

  </ion-list>

</ion-content>

For example:


#11

If possible, I would move those function calls (such as isValidMenu and isValidMenuItem) out of the template and into the controller, where they can be called only when the underlying data is updated. Angular’s change detection has to be aggressive and assume that every function call will return a different value, so they will get called on every change detection cycle. Generally, you can do this more intelligently and update a property in the item or beer object, so that change detection knows more accurately when they have changed.


#12

Thanks guys. It was very easy. You information was very important for me.