Mongo insert not reactive


#1

I have built a basic form similar to the one used in the angular2 meteor tutorial (https://www.angular-meteor.com/tutorials/socially/angular2/adding-removing-objects-and-angular-event-handling), however when I press the submit button the page does not automatically reflect the update - If I refresh the page it then shows up.

Could someone suggest what I might be doing wrong?

I seem to remember when doing the tutorial it ‘just works’ when inserting a document from the console…


#2

From you description it sounds like what you’re rendering doesn’t come from a reactive source, i.e. it doesn’t update when the source updates. Without more details I can’t really know what’s going on.


#3

Hey, thanks for your reply.
I’m loading from my collection with something like this (my ‘entity’ component):

this.route.params.subscribe((params) => {
  this.entityId = params['entityId'];

  this.subscribe('entities', () => {
    this.entity = Entities.findOne({'_id':this.entityId});
  }, true);

  console.log(this.entity);
});

Then I have an ‘entityForm’ as a directive in there which adds a new entity like this:

  addEntity(entity) {
    if (this.entityForm.valid) {

      Entities.insert({
        job: {
          jobId: this.jobId,
          jobName: this.jobName
        },
        name: entity.name,
        type: entity.type,
        status: entity.status,
        thumbUrl: entity.thumbUrl,
        description: entity.description,
        public: entity.public
      });
    }
  }

Do I need some way of reporting back to the main component after a successful insert?


#4

I managed to get it working. I had forgotten to use the Tracker.autorun() function. I also had posted the wrong code above (sorry), I was actually loading finding the documents then looping through them and sorting them into two separate categories like:

          this.entities = Entities.find({ "job.jobId": this.jobId }).forEach((item) => {
            if (idx == 0) {
              this.first = item;
            }
            // sort into assets and shots
            if (item.type === 'asset') {
              this.assets.push(item);
            }
            else if (item.type === 'shot') {
              this.shots.push(item);
            }

            idx += 1;
          });

If I remove the foreach and then do my ngFor over the ‘entities’ variable it now works (with Tracker.autorun()). Is there a way I could keep the method above (with the foreach) and make it reactive?


#5

im struggling to do it any other way since I can’t use ngIf on the same element as ngFor so I can’t sort them at that stage, so could someone help me get the above code working and reactive? Unless there is a better way of doing this?


#6

It could look like:

this.tracker = Tracker.autorun(() => {
  // Reset lists
  this.assets.length = 0;
  this.shots.length = 0;
  
  // Update lists
  this.entities = Entities.find({ "job.jobId": this.jobId }).forEach((item, index) => {
    if (index == 0) {
      this.first = item;
    }
    // sort into assets and shots
    if (item.type === 'asset') {
      this.assets.push(item);
    } else if (item.type === 'shot') {
      this.shots.push(item);
    }
  });
});

When you are done with the reactive source (for example, when your component is destroyed), stop the Tracker computation:

this.tracker.stop();

Alternatively, you can use the angular-meteor APIs: doc & tuto.


#7

hey, thanks for the suggestion, I just tried that out and its not reactive… I have to refresh the page to see the results


#9

It seems, in my case that ‘entities’ is fully reactive - as soon as I submit my form to insert a new document it pops up straight away. With ‘assets’ and ‘shots’ it doesn’t, but it does show up if I click inside a different field of the form… Is this because of the ngModel is somehow causing angular to update? Just for the sake of clarity, this is my component now:

export class EntitiesComponent  extends MeteorComponent {
  entities: Mongo.Cursor<Object>;
  first: Object;
  subscription: any;
  jobId: string;
  tracker: any;
  assets = [];
  shots = [];

  constructor(private _entityService: EntityService,
              private route: ActivatedRoute) { 
    super();

    this.route.params.subscribe((params) => {
      
      this.subscribe('entities', () => {
        this.jobId = params['jobId'];

          this.tracker = Tracker.autorun(() => {
            // Reset lists
            this.assets.length = 0;
            this.shots.length = 0;
            
            // Update lists
            this.entities = Entities.find({ "job.jobId": this.jobId });

            this.entities.forEach((item, index) => {
              if (index == 0) {
                this.first = item;
              }
              // sort into assets and shots
              if (item.type === 'asset') {
                this.assets.push(item);
              } else if (item.type === 'shot') {
                this.shots.push(item);
              }
            });
          });

      }, true);

    });
  }

  ngOnInit() {}
}

#10

Did you try the autorun method from MeteorComponent?


#11

Yea, same result. That’s just a wrapper for Tracker.autorun() anyway right?