0

i need to get data from Firebase in descending order .

When the component loads for the first time it happens fine.

  fetchData(){
    return this.af.list('/path/path/',{
      query: {
        orderByChild: 'createdAt'
      }
    }).map(arr => {return arr.reverse();});
  }

The data from fetch ads is stored in a var and then displayed.

But now the problem is the var is modified at run time the user can update the var array , or delete or add to it .

And when ever any of these operations takes place the data is modified on the firebase db and that calls the fetch data again .

But then the reverse is again revesed rendering the whole thing use less.

By this i mean is after the first component load the var is 1,2,3,4. But then when we add to var instead of becoming 1,2,3,4,5 it becomes 5,4,3,2,1.

This is very confusing but i a tried lot but not able to fix this.

UPDATE

 ngOnInit() {

    this.display = this.route.snapshot.data['Auth'];

    if(this.display){
      this.showProgress = true;
      this.user = JSON.parse(localStorage.getItem("user"));
      this.service.fetchData().subscribe((data) => {
        this.comments = data;
        this.showProgress = false;
      });
    } else {
      this.afAuth.authState.subscribe((data) => {
        if (data) {
          localStorage.setItem("user", JSON.stringify(data));
          this.user = data;
          this.service.fetchData().subscribe((res) => {
            this.comments = res;
            this.showProgress = false;
          });
        } else {
          this.comments = null;
        }
      });

This is what happens on run time rest all are the crud functions of angular2firebase that happens when we add update or delete

I tried using pipes for the same but then it causes problem when getting the index so i dropped the plan as it was getting too complex

add(){
    this.service.postComment(this.comment, this.user);
  }

  editComment(key:string,updatedComment:any){
    const index = ((this.page-1)*5)+i;
    const updated = this.comments[index];
    updated.comment  = comment;
    this.service.editComment(updated.$key,updated);
  }

  deleteComment(key:String){
   this.service.deleteComment(this.comments[index].$key);
  }
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
INFOSYS
  • 1,465
  • 9
  • 23
  • 50
  • Can we see where you assign `fetchData()` to the value? – SrAxi Jul 19 '17 at 08:35
  • @SrAxi updated the ngOnint this is where it is fired – INFOSYS Jul 19 '17 at 08:40
  • So the issue is that on init `this.comments` gets the list as you want it (reversed), but the second time it's getting it ordered? – SrAxi Jul 19 '17 at 08:44
  • Show me the code for this: *"But now the problem is the var is modified at run time the user can update the var array"*, please. I'm pretty sure the issue is in that logic. – SrAxi Jul 19 '17 at 08:47
  • what might be the error here ? its just plain firebase commands – INFOSYS Jul 19 '17 at 08:51
  • Where is i coming from inside editComment? – JGFMK Jul 19 '17 at 09:14
  • Also have you tried looking at the data in the Firebase console before and after updates. Are the nodes getting overwritten so 1 becomes 5 etc on update. Or is it a case of something else during the reloading? and insert a do(console.log) into the subscribe chain maybe. – JGFMK Jul 19 '17 at 09:18
  • the nodes remain the same , just at the time of load it changes – INFOSYS Jul 19 '17 at 09:19
  • Is it plausible that somehow you are getting double subscriptions? So you need to unsubscribe before re-subscribing perhaps? i.e. ngInit is only place you subscribe? – JGFMK Jul 19 '17 at 09:23
  • yes @JGFMK that is the only place i am subscribing i am not sure how its comming twice – INFOSYS Jul 19 '17 at 09:25
  • @JGFMK but if you look at the code the subscribe is called twice but based on condition is that the reason ? but it is inside a if else block – INFOSYS Jul 19 '17 at 09:27
  • I think you should definitely update your question to show that finding. I'm not sure why your getting the double subscription. Is this.route.snapshot.data['Auth'] asynchronous maybe? That's out of my realm of expertise. But it seems extremely probable that's the root of your problem. Others might not see the last few comments in out exchange. – JGFMK Jul 19 '17 at 09:34
  • that route is async but it dosnt call the angular fire , this is the 80% code rest are all vars – INFOSYS Jul 19 '17 at 09:37
  • I'm wondering if you can somehow chain something like a do off the this.route.snapshot.data['Auth'] and put the whole if block inside.. It may be some type of similar syntactic sugar that's required. Router Data Resolvers maybe... – JGFMK Jul 19 '17 at 09:39
  • Take a look at my updated answer - At the end it points you to how to implement a Router Data Resolver.. – JGFMK Jul 19 '17 at 09:51

2 Answers2

2

I believe you have a typo here:

  editComment(key:string,updatedComment:any){
    this.service.editComment(updatedComment.$key, updatedComment); // I changed `updated` to `updatedComment`
  }

Another thing you could do, is following on your reverse custom pipe approach, and when you do that, remove reverse() from your map() in fetchData().

Reverse Pipe:

import {Pipe} from 'angular2/core';

@Pipe({
  name: 'reverse',
  pure: false
})
export class ReversePipe {
  transform (values) {
    if (values) {
      return values.reverse();
    }
  }
}

UPDATE:

Try declaring the mapped and reversed response as a FirebaseListObservable<any[]>.

 fetchData(){
    return this.af.list('/path/path/',{
      query: {
        orderByChild: 'createdAt'
      }
    }).map((array) => array.reverse()) as FirebaseListObservable<any[]>;
  }
SrAxi
  • 19,787
  • 11
  • 46
  • 65
  • i have tried the pipes approach but i fires too many times and also i renderer components using renderer 2 by fetching dynamic id thats dosen't work properly . and that not a typo i updated the question – INFOSYS Jul 19 '17 at 09:08
  • one unusual behaviour i have noticed when i add a new comment the fetch data is called twice why ? – INFOSYS Jul 19 '17 at 09:12
  • After your update now when i update the when i insert the reverse is called 3 times once on page load and twice after submit so it works but i delete it calls it only once so the reverse revse cancels each other – INFOSYS Jul 19 '17 at 09:20
0

Does this sort of overview help?

app-module.ts

import {firebaseConfig} from "../firebase.config";
@ngModule({
 imports: [
  AngularFireModule.initializeApp(firebaseConfig)

  ]

})

firebase.config.ts

export const firebaseConfig = {
    apiKey: "<your api key>",
    authDomain: "....",
    databaseURL: "....",
    storageBucket: "...",
    messagingSenderId: "..."
};

my-component.ts

import {Component, OnInit} rrom '@angular/core';
import {AngularFireDatabase} from 'angularfire2';
import {Data} from "../shared/model/data"; //insert your domain class here & in code

export class MyComponent implements OnInit {
   data: Data[];
   constructor(private db: AngularFireDatabase) {}

    ngOnInit() {
        this.db.list('data', {
            query: {
                orderByKey: true,
                limitToLast: 10
            }
        })
            .do(console.log)
            .subscribe(
                data => this.data = data
            );
    }
}

my-component.html

<table *ngIf="data">
  <tr *ngFor="let row of data">
      <td>{{row.column}}</td>
   </tr>
</table>
<div *ngIf="! data">Loading ...</div>

Here are the links for other users coming to this thread for the first time:

Update

I believe from out dialog in the comments for your original question, the problem lies in the fact that

this.display = this.route.snapshot.data['Auth'];

is an asynchronous process, and consequently you get subscriptions to both halves of the if else branch.

Your need a RouterDataResolver and move the if/else block into it.
See my question here, that will give you a roadmap for how to proceed.

JGFMK
  • 8,425
  • 4
  • 58
  • 92