Ember.js 2.2 - How to update Route model from a Component?

With Ember 2.2.0, I have a Route:

Dash.BacklogReportsRoute = Ember.Route.extend
  model: ->
    @store.queryRecord "report", newest: true

and a Component:

Dash.BacklogReportComponent = Ember.Component.extend
  report: null
  actions:
    generate: ->
      # Send the request.
      $.ajax
        type: "post",
        url: "/reports/generate/#{new Date().getFullYear()}",
        success: =>
          # Update the model.
          # TODO - how to reload the model in place? Or at least just refresh
          # the Route so we don't have to reload the entire app.
          window.location.reload()

which includes as part of the template:

<p>
  Report was generated {{report.timestamp}}.
</p>

where timestamp is a computed property on the Report model.


The Route's model is the most recent Report object, and via the POST the generate action causes the server to create a newer (thus more recent) Report. I want to update the timestamp of that [newer] Report.

My question is, in Ember 2, how can I cause the Route to refresh itself? I'm new to Ember so I'm not sure if it's possible to access the Route directly from within a Component (or if I can, if it's a good idea). I don't think just reloading the model would work, because after a successful POST a different model (i.e. a record with a different id) will be returned by @store.queryRecord "report", newest: true than when the page loaded. The existing model will be the same after the POST.

Alternatively, I'd be perfectly happy completely rerendering the Route (it's a very simple page) or transitioning to "this" page again, but I can't figure out how to do that.

For now I'm simply forcing an old-school page window.location.reload().


Looking at this another way, perhaps there's a more idiomatic way to approach this problem with Ember.

Should I be loading in all (or some) Reports with the Route, and forcing a refresh on that Collection after the POST? I see Enumerable has a .firstObject property - is that a computed property (in other words, if my Routes model is a Collection of Reports and I push on to the front of that Collection, would that change propagate through .firstObject references automatically?)

Answers


Well you can't actually access the route directly from the component. But that is no problem since you can use actions to achieve the same effect.

So first you need to send an action from your generate action in your component:

Dash.BacklogReportComponent = Ember.Component.extend
  report: null
  actions:
    generate: ->
      # Send the request.
      $.ajax
        type: "post",
        url: "/reports/generate/#{new Date().getFullYear()}",
        success: =>
          @sendAction('didGenerate')

Next you need to hook up the action in the template, so your controller/route gets notified when it is called:

{{backlog-report report=report didGenerate='didGenerateReport'}}

And now you can "catch" that action in your controller or route. We will do it in ther route so we can refresh it:

Dash.BacklogReportsRoute = Ember.Route.extend
  actions:
    didGenerateReport: ->
      @refresh()
  model: ->
    @store.queryRecord "report", newest: true

Sorry if I made any mistakes with CoffeScript (didn't use it for quiet some time). Also there are other things you could improve. Generally I wouldn't put the ajax call in the component, I would put it in the controller/route if possible and call it with an action (I just have the experience that it's best to avoid putting ajax calls in a component, though there are usecases for it).

I would generally propose to read all of the ember guides if you didn't yet do so. They are pretty good and while you won't understand everything from the first read, you will at least more or less know what to look for, or what is possible.


If you need to manually reload the page, there really should be a better way. Ember as other similar frameworks are an SPA (single page application) and do their magic when updating only parts of the page very efficiently.


that being said, if you want to access the router from the controller/component by sending an action to the router and handling the changes in that action.

see action bubbling https://guides.emberjs.com/v1.10.0/templates/actions/


Need Your Help

Use multiselect false property with checkboxCellTemplate

angularjs angular-ui-bootstrap ng-grid

I have an ng-grid that utilizes the showSelectionCheckbox: true property with a custom checkboxCellTemplate.

How do I select one exact substring but not another from a string in mysql?

mysql regex

I have the following entries stored in an attribute in mysql: