Urigo / angular2-meteor

Angular 2.0 and Meteor - the perfect stack
http://www.angular-meteor.com/
298 stars 61 forks source link

How to provide Array access for Mongo.Cursor? #143

Closed dotansimha closed 8 years ago

dotansimha commented 8 years ago

The current Differ is not enough, it has great advantages, but one big disadvantage - it does not provide access to the Array that ngFor creates, so the access is only available within the view, and it is not possible to get that array in the component's class. It is possible to perform MyCol.fetch() but it is not reactive, and the effort of making it reactive is too much, because every user who writes real application will do it, and for each one of his collections in use.

Some ideas I had:

Implemented @Mongo.Cursor decorator for some tryouts:

export function MongoCursor(target:Object, propertyKey:string | symbol):void {
  let dataArray = [];

  Object.defineProperty(target, propertyKey, {
    enumerable: true,
    configurable: false,
    get: function () {
      return dataArray;
    },
    set: function (newCursor) {
      if (newCursor instanceof Mongo.Cursor) {
        dataArray = newCursor.fetch();
      }
      else {
        throw new Error('The value of ' + propertyKey + ' cursor, must be Mongo.Cursor!');
      }
    }
  });
}

It works, the actual usage is as follow:

export class MyClass extends MeteorComponent {
     @MongoCursor
     myData : Array<any> | Mongo.Cursor<any>;

     constructor() {
         this.autorun(() => {  // We can even put the autorun on the `fetch` itself on the decorator's code and make even more simple
               this.myData = MyCollection.find();
         });
     }
}
barbatus commented 8 years ago

Am i right that the last construction is equivalent to (without @MongoCursor):

constructor()  {
   this.autorun(() => { 
       this.myData = MyCollection.find().fetch();
   });
}

Hence, it makes sense to my mind if autorun is moved inside. Though, not sure about the name (it's more like @Fetch), and how big is overhead if the use had to write autorun and fetch himself.

derekkite commented 8 years ago

Ignore this if I don't know what I'm talking about, but what about a service exposing an array to the component? Get the data stuff out of the component and into a service class with the autorun and subscribe functions. Any update or insert, subscribing and the like is better encapsulated, allowing component reuse for different collections, and moving any of the mongo specific calls into the service. There would need to be an ngclose call for cleanup, and the service could be injected into either the component or bootstrap. I'm not certain if there are lifecycle hooks into injectables for cleanup.

shalaby commented 8 years ago

@dotansimha any solution? workaround?

barbatus commented 8 years ago

RxJS-compatible verison of Meteor API added https://github.com/Urigo/meteor-rxjs