FlowRouter, [triggersEnter] with Database-Query [solved]

Hi,

I have a chatroom that can be locked so no more users can enter this room. For the link that leads to the closed chatroom I use simply a database query to check if the room is closed and then return if thats the case.

Chatrooms.findOne({name: Url-Param, isClosed: true})

There’s a problem with this approach. If the user just enters the URL to the room directly he gets sent there without that check. Thats why I tried it on a similar approach with Flowrouters [triggersEnter] to check it like that before the route is entered.

FlowRouter.route('/room/:name/:char', {
  name: 'App.room',
  triggersEnter: [trackRouteEntry],
  action: function(params, queryParams) {
// test, also gives 0
 console.log(Channels.find({name:params.name}).count());
    BlazeLayout.render('App_body', { main: 'room' });
  },
});


function trackRouteEntry(queryParams, params) {
  // "queryParams.params.name provides name of the chatroom
  if (Channels.findOne({name: queryParams.params.name, isClosed: false})) {
    console.log("this Room is not closed")
  } else {
    console.log("this Room is closed");
   // test, count gives 0
    console.log(Channels.find({name: queryParams.params.name}).count());  
  }
}

I assume it doesn’t work because the subscriptions for the database data can’t exist since it gets executed before the route is entered. I’m out of ideas.

Is there any way to check for a database field before the route is entered or is the whole approach going in the wrong direction?

Additional Information: On creation a room is always open and not closed.

I would appreciate any help, thanks!

I would do this in a RoomContainer. A component that is purely responsible for loading data and performing checks.

Template.roomContainer.onCreated(function () {
  const room = FlowRouter.getParam('room');
  this.loading = new ReactiveVar(true);
  this.subscribe('roomData', room, () => {\
    // This fires when the subscription is ready and data is available
    const channel = Channels.findOne({ name: room }));
    if (!channel || channel.isClosed) {
      // maybe set error state / toast / notification
      // redirect to somewhere
      return
    }
    // set loading to false
    this.loading.set(false);
  });
});
Template.roomContainer.helpers({
  roomData() { 
    return Channels.findOne({name: queryParams.params.name, isClosed: false}));
  }
})
<template name="roomContainer">
  {{#if loading}}
  {{> loader }}
  {{else}}
  {{> room roomData }}
  {{/if}}
</template>

Alternatively, you could display a room closed page instead of redirecting, but that’s up to you

The nice part about separating out the data loading and checks from the room view, is that testing the room view is much easier, as it recieves its data from props/data, so you can pass in test data without needing to populate a database first

1 Like

Oh, and if you want to use FlowRouter for the checks, use the waitOn hooks!

You can return a subscription hook and it will wait until the data is ready before calling the action.

This means moving the checks from the triggers to the action

Thank you, the roomContainer-solution works perfectly! :hearts:

1 Like