Adding new data via websocket when using store.query in the route

My application uses ember-phoenix- based websocket service to push new entries from the API to the store. I would like these new entries to appear in my template when they were added.

I have a route where the model hook returns a filtered request promise:

import Ember from 'ember';

const {
  get,
  inject,
} = Ember;

export default Ember.Route.extend({
  socket: inject.service(),

  model(params) {
    return this.store.query('my-model', {filter: {date: params.date}})
  },

  afterModel() {
    get(this, 'socket').joinSchedule();
  },

  resetController() {
    get(this, 'socket').leaveSchedule();
  },

});

When new entries are transferred to the repository via websocket, they are not displayed by my template due to how it works store.query. If I changed store.queryto store.findAll, new entries will be displayed, but I want my route to load only a subset of all entries based on the date request parameter.

, - , . ? , , ?

:

import Ember from 'ember';
import PhoenixSocket from 'phoenix/services/phoenix-socket';

const {
  get,
  inject,
} = Ember;

export default PhoenixSocket.extend({
  session: inject.service(),
  store:   inject.service(),

  joinSchedule() {
    const channel = this.joinChannel(`v1:my-model`);

    channel.on('sync', (payload) => this._handleSync(payload));
  },

  _handleSync(payload) {
    get(this, 'store').pushPayload(payload);
  },
});
+4
3

1
Ember.Evented . twiddle .

socket

  • socket Ember.Evented

    export default PhoenixSocket.extend(Ember.Evented, {
  • myModelDataLoaded, , myModelDataLoaded.

     _handleSync(payload) {
            get(this, 'store').pushPayload(payload);
            this.trigger('myModelDataLoaded'); //this will call the functions subscribed to myModelDataLoaded.        
        }

  • myModelDataLoaded
afterModel() {
        get(this, 'socket').joinSchedule();
        get(this, 'socket').on('myModelDataLoaded', this, this.refreshRoute); //we are subscribing to myModelDataLoaded
    }
  • refreshRoute refresh.

       refreshRoute() {
            this.refresh(); //forcing this route to refresh
        }
    
  • , off , resetController, deactivate hook.
    resetController() {
        get(this, 'socket').leaveSchedule();
        get(this, 'socket').off('myModelDataLoaded', this, this.refreshRoute);
    }
    

2.
, peekAll .

,
 1. postModel, .
 2. postModelObserver, postModel.[], , , myModelObserver, refreshRoute . refresh. , beforeModel, model, afterModel.

, , , . , , this.get('myModel') init

import Ember from 'ember';
const { computed } = Ember;
export default Ember.Controller.extend({
    init() {
        this._super(...arguments);
        this.get('postModel');//this is just to trigger myModel computed property
    },
    postModel: computed(function() {
        return this.get('store').peekAll('post');
    }),
    postModelObserver: Ember.observer('postModel.[]', function() {
        this.send('refreshRoute');
    })
});

- refreshRoute , refresh .

import Ember from 'ember';

const {
    get,
    inject,
} = Ember;

export default Ember.Route.extend({
    socket: inject.service(),
    model(params) {
        return this.store.query('my-model', { filter: { date: params.date } })
    },

    afterModel() {
        get(this, 'socket').joinSchedule();
    },

    resetController() {
        get(this, 'socket').leaveSchedule();
    },
    actions:{
        refreshRoute() {
            this.refresh();
        },
    }
});
+3
+1

This is not the best way, but one way to make your existing code is to use a callback.

import Ember from 'ember';

const {
 get,
 inject,
} = Ember;

export default Ember.Route.extend({
  socket: inject.service(),

  model(params) {
    return this.store.query('my-model', {filter: {date: params.date}})
  },

  afterModel() {
    let cb = (myModelRecord) => {
      this.get('model').push(myModelRecord);
    };
    get(this, 'socket').joinSchedule(cb);
  },

  resetController() {
    get(this, 'socket').leaveSchedule();
  },

});

Calling a callback method on a socket service,

 import Ember from 'ember';
 import PhoenixSocket from 'phoenix/services/phoenix-socket';

 const {
   get,
   inject,
 } = Ember;

 export default PhoenixSocket.extend({
   session: inject.service(),
   store:   inject.service(),

   joinSchedule(cb) {
     const channel = this.joinChannel(`v1:my-model`);

     channel.on('sync', (payload) => cb(this._handleSync(payload)));
   },

  _handleSync(payload) {
    return get(this, 'store').pushPayload(payload);
  },
});
0
source

Source: https://habr.com/ru/post/1667298/


All Articles