No template update after createRecord with findQuery fetching - ember.js

I'm wonder why my template doesn't get updated after createRecord when using findQuery to fetch data.
When changing this return this.store.findQuery('timetracking', {year: year, month: month, user_id: user_id}); to return this.store.find('timetracking'); the template gets updated with my new records.
I don't want to fetch all records to save bandwith, but when using only find/findQuery with query params, my newly created records doesn't show up in my template.
Do I have to do a "force" reload? And how to do this?
Update
The Ember inspector shows the new records.

findQuery puts the job of filtering on the server's back. Ember Data assumes that the results that were returned are the only results that are associated with that collection. find with no query or id (findAll) will always return all records found in the store, because it realizes you weren't looking for any filtered set, if you create a new record it gladly knows to include it in all of the available records. You can manually push a record into a collection of records using pushObject.
// assuming you're in the context of your `findQuery` results, and they are the model
var model = this.get('model'),
record = this.store.createRecord('timetracking', {...});
model.pushObject(record);

Related

How to peek a record using name rather then using id in ember

So in rails we could find a record by name, id etc, similarly i want to do in ember without making a server request
I have a model called person{id, name}. If i want to peek a record by id i do this:
this.get('store').peekRecord('person', id)
which gives me the record based on id, but now i want to peek a record with a particular name, i tried something like this:
this.get('store').peekRecord('person', {name: "testname"})
which dose not seem to work.
i need a way peek a record using just the name
You can only peekRecord using the unique identifier for the model, which is id property. If you do want to make a request then queryRecord is what you want. but you don't want to make a request so the only choice is peekAll and filter the result,
let allRecord = this.get('store').peekAll('person');
let filteredResult = allRecord.filterBy('name','testname');
//filteredResult is an array of matching records

How do I save all locally created records in ember / ember data?

Currently, the Ember Data filter method has been deprecated. What's the best way to approach saving all new/updated records of a particular type?
You can call save() on a RecordArray so I have been doing:
this.get('store').peekAll('record-type').save() but I'm not sure if there's some better way to go about it.
I would go with:
this.get('store').findAll('users').then((users) => {
users
.filterBy('dirtyType', 'created') // filter for unsaved records
.invoke('save'); // call the save method on each model instance
});
If you return the users object you get an array of promises that you could catch with Ember.RSVP.all(), to listen for when all the users have been saved.

Ember - Fetching live records with meta information

I have created a comment model and trying to fetch all comments records. But I need a meta info total comments which is getting as a separate attribute outside comments array.
I am using Ember store.query to fetch records from rest service(I tried store.findAll, but it is giving me only record array of comments in promise response. Is it possible to modify that?). I am getting the records with total comments(meta) while using store.query(), but that record array is not getting updated when we save new records.
After doing some analysis I found that we can use filter for loading the live record, but filter is now deprecated in Ember(Ember 2.5.1). From the documentation It is clear that we can use ember-data-filter for loading live record. But I am confused to use that addon(Mentioned like it has some memory leakage issue) and not sure whether I will get meta information from response. Is there is any other way to fetch live records with meta information from the response.
Anyone please suggest a solution
After doing some analysis, I found a solution to access meta data using store.findAll(). We can use typeMapFor in the findAll response to get the meta info in the response
store.typeMapFor(response.type)
Full code below,
store.findAll("comment").then(function(response) {
var meta = store.typeMapFor(response.type);
// your meta info will be in meta.metadata
// var totalComments = meta.metadata.totalComments;
});
And the response record array is liveRecords which will get updated automatically, if we save new records.
store.query("comment").then(function(response) {
var meta = response.get("meta");
// We will get meta like this but reponse record array is not a liveRecords
});
Response getting from store.query() is just a recordArray (not liveRecords) which will not get updated with new records
If you want an array of all records that updates as new records are populated you can use peekAll which returns a live record array.
Added Code sample:
loadRecords: function (){
this.set('allComments', store.peekAll('comment'));
this.store.findAll('comment');
},
recordCount: Ember.computed.alias('allComments.length')

Updating and creating a new instance at the same time

When a user updates an invoice form, i want to create a new invoice record with the updated attributes, but also change one or two fields of the old record and save it, too.
How would the outline of a controller action look like which could accomplish this?
Instead of a controller action i put the code in the model, using callbacks:
before_save do |rec|
if !rec.new_record?
attrb = rec.attributes.delete_if{|k, v| ["id"].include? k }
Book.create(attrb)
rec.restore_attributes
rec.year = rec.year + 2 # some custom change
true
end
end
I keep all attributes unless the 'id' (otherwise i get an error) for create a new record with the new attributes.
Then i restore the attributes of the existing record. I do some custom change before saving.
I am rather new with Rails but this seems pretty straightforward. As you mention the user is 'updating" an invoice, your controller view has probably been passed all the data available to the user for further change.
When submitting the form, your update action can easily update the current record data, as well as creating a new one on top of this
Though as it is automated, you need to make clear:
if a new invoice record is created each time an invoice record is
updated (thi can create a lot of copies of the same invoice)
how you make the old record an archive to avoid duplicates
can the 'additional" amendments be automated and easily processed through an algorithm...
Nested attributes made things a bit tricky. So in order to create new instances I had to use the dup method for both the resource and its nested items.
Generally, it is advisable to keep the controllers slim and make the models fat. Nevertheless, I have decided to include this code into my Invoices controller:
def revise_save
#contact = Contact.find(params[:contact_id])
#invoice = #contact.invoices.find(params[:invoice_id])
#invoice_old = #invoice.dup
#invoice.invoice_items.each do |item|
#invoice_old.invoice_items << item.dup
end
#invoice.datum = DateTime.now.to_date
# archive old invoice
# #invoice_old. ...
#invoice_old.save
# make old new invoice
#invoice.datum = Time.now
# ...
#invoice.update(invoice_params)
redirect_to invoices_path
end
Note that in this solution the currently edited (original) invoice becomes the new invoice, the old one is paradoxically created anew.
Thanks to #iwan-b for pointing me in the right direction.

Can i hide the query params from the URL?

In my Ember.js Application, I am dealing with query params for list updates. I have one strange use case, in which I don’t the URL to be updated with certain query params. How can I achieve this?
I assume you want to reload your model with parameters that are different than the ones in your application route? And you keep your application route parameters synced using queryParams?
In your route's model function you can filter your model data by the same query params (that appear in the address bar) but you can add some logic that extracts additional parameters either from the controller or other place and these parameters the data fetching query. Example:
model: function(queryParams) {
var params = queryParams;
params.additional_filter = this.controllerFor('mycontroller').get('additional_filter');
return this.store.find('mymodel', params);
}
Also if you want to explicitly reload the model you will need to call Router.refresh() function.