adriancarriger / angularfire2-offline

🔌 A simple wrapper for AngularFire2 to read and write to Firebase while offline, even after a complete refresh.
https://angularfire2-offline.firebaseapp.com/
MIT License
207 stars 48 forks source link

Offline update different than online update. #60

Open tja4472 opened 7 years ago

tja4472 commented 7 years ago

Hello again

Online update allows for the update of individual properties.

this.fb_CurrentTodos.update(itemsToSave[x].$key, { index: x });

Offline: Just the updated property is returned.

todo.data.service.ts:24 >>>>>>>>>>AngularFireOfflineDatabase.list> (2) [{…}, {…}]
todo.data.service.ts:87 fromFirebaseTodo> {index: 0, $key: "-KXpuvXAo3jYqlp5s8OH", $exists: ƒ}
todo.data.service.ts:87 fromFirebaseTodo> {index: 1, $key: "-KrVLgUO1C-nNeE4fK98", $exists: ƒ}

Proposed fix

emulate-list.ts - processEmulation

 } else if (method === 'update') {
      let found = false;
      let itemToUpdateIndex = this.observableValue.findIndex(item => item.$key == key);

      if (itemToUpdateIndex > -1) {
        found = true;

        const cc_newValue = Object.assign(this.observableValue[itemToUpdateIndex], value );
        this.observableValue[itemToUpdateIndex] = cc_newValue;
        console.log('cc_newValue>', cc_newValue);
/*
        const aa_newValue = { ...this.observableValue[itemToUpdateIndex], ...value };
        console.log('aa_newValue>', aa_newValue);

        const bb_newValue = unwrap(key, aa_newValue, () => aa_newValue !== null);
        console.log('bb_newValue>', bb_newValue);

        this.observableValue[itemToUpdateIndex] = bb_newValue;
*/        
      }

      /*
            this.observableValue.forEach((item, index) => {
              if (item.$key === key) {
                found = true;
                this.observableValue[index] = newValue;
              }
            });
      */
      if (!found) {
        this.observableValue.push(newValue);
      }
    } else { // `remove` is the only remaining option

internal-list-observable.ts

  uniqueNext(newValue) {
    // Sort
    console.log('##uniqueNext');
    console.log('newValue>', newValue);
    console.log('previousValue>', this.previousValue);

    if (this.previousValue) { this.previousValue.sort((a, b) => a.$key - b.$key); }
    if (newValue) { newValue.sort((a, b) => a.$key - b.$key); }

    if (this.updated > 1 || (stringify(this.previousValue) !== stringify(newValue))) {
      // this.previousValue = Object.assign([], newValue);
      let deepClone = Object.assign([], newValue);
      deepClone = deepClone.map(x => {
        let b = Object.assign({}, x);
        unwrap(b.$key, b, () => b !== null);
        return b;
      });
      this.previousValue = deepClone;
      this.next(newValue);
      this.updated++;
    }
  }

hth Tim

tja4472 commented 7 years ago

On reflection it would be best to leave internal-list-observable.ts alone.

emulate-list.ts - processEmulation will then be

        const aa_newValue = { ...this.observableValue[itemToUpdateIndex], ...value };
        console.log('aa_newValue>', aa_newValue);

        const bb_newValue = unwrap(key, aa_newValue, () => aa_newValue !== null);
        console.log('bb_newValue>', bb_newValue);

        this.observableValue[itemToUpdateIndex] = bb_newValue;
Pl4yeR commented 7 years ago

I'm facing an issue: I have a list of elements, where each element is like: { property1: "this is one", property2: "this is two" } When I do this.db.list('/elements').update(elementId, {property1: "this is NEW one"}); property1 is updated, but property2 is DELETED, just like a SET instead of an UPDATE.

Is this the problem you are describing above?

tja4472 commented 7 years ago

Yes, I'm afraid so.