I am developing an app where there is a huge list of items, loaded from the server by ember-data. This lists can be filtered by different fields, like date.
When you load this route for the first time, it is filtered by date: it only loads the current year items. However, the user can change those filters.
When you transition to another route and come back, the visible filters are the same as when you left, ember seems to remember them. However, since the model is loaded by the route before the controller exists and the filters are available, it loads all the current year ones.
Therefore, the result is that the user is seeing a list of all current-year items, and a set of filters that may not match.
What I would love is for the route to not reload the model if it is already available, so to save time and network; but any solution would be appreciated.
You could move the GET to the controller which will not be regenerated on route change, if the controller is already present all your previous models and filters are still present
Get the last selected filter options from the controller in beforeModel:... or model:... method to load your data via query (if possible)
If you´re sure all the data is already loaded use peekRecords to avoid a new network request
Related
I have a database table called Accounts and there's a column isCustomer.
To make my /Entity/Customer.php only return accounts that are actual customers I used a Custom Doctrine ORM Extension
There is also a relation with the Contacts table. I'd like to add Contacts to Customer when the /customers URL is requested. This relation exists and is working properly, and is also eager loading.
The moment I created the /Doctrine/CustomerExtension.php the result set only consists of customer accounts (with contacts), like I expected.
But at the same time the Eager Loading ORM Extension doesn't work anymore.
All relations are lazy loaded now even with #ORM\ManyToOne(fetch="EAGER") on every relationship.
How do I add $queryBuilder->andWhere('isCustomer = 1'); by default AND keep eager loading?
My first attempt has been to add normalizationContext={ "groups": {"boost"} } to /Entity/Customer.php and put all the properties in that group. It didn't fix eager loading :(
I have read Ember docs related to Substates etc and I understand how it works. In my current application my loading.hbs and other child loading.hbs templates work fine.
I just want to discuss a use case.
In my route A, in my model function I do fetchAll for my model.
I go to Route A, First time api request is sent and I see my loading screen.
now I navigate to some other route B.
now I come back to first route A, api request is sent again but this
time loading screen is not shown.
I want to develop my understanding here. Now the second time loading screen is not shown which tells us that store had data so there is no sense to put it on loading and after fetch store sent request to sync with backend.
QUESTION
Now I want to know if this is a default behaviour of Ember with Ember-data?
To show this loading screen, will I have to do something manually?
Ideally what I want is, if on second request data was fetched then show it and at the same time show loader to tell user that it is syncing with backend as well.
I know everything can be done manually, I don't want to reinvent the wheel or do things in non-conventional way. So I want to know best optimized solution for this as provided by Ember which an experienced Ember developer can help me understand.
Thanks in advance.
Now I want to know if this is a default behaviour of Ember with
Ember-data?
Yes, that's the default behavior of Ember data when you do a findRecord or findAll where shouldBackgroundReloadRecord or shouldBackgroundReloadAll event of the adapter respectively, is defaulted to true. You can turn this off by returning false and ensuring shouldReloadAll or shouldReloadRecord respectively are set at true to ensure the request always hits the API and not fetches from cache.
Ideally, showing data immediately on the screen is always advisable as it has a better UX in terms of giving the user a feel that data is already there and that some parts of the data is being fetched. Check here
To show this loading screen, will I have to do something manually?
You may also want to read this
To add further details after my own research, I found helpful and relevant details in Ember docs.This is all about caching.
If records were already there then promise will be resolved immediately that's why I don't see loading screen for already loaded record, at the same time Ember-Data syncs with backend as well and re-render the template.
Ember Model Docs
Caching
The store will automatically cache records for you. If a record had already been loaded, asking for it a second time will always return the same object instance. This minimizes the number of round-trips to the server, and allows your application to render its UI to the user as fast as possible.
For example, the first time your application asks the store for a person record with an ID of 1, it will fetch that information from your server.
However, the next time your app asks for a person with ID 1, the store will notice that it had already retrieved and cached that information from the server. Instead of sending another request for the same information, it will give your application the same record it had provided it the first time. This feature—always returning the same record object, no matter how many times you look it up—is sometimes called an identity map.
Using an identity map is important because it ensures that changes you make in one part of your UI are propagated to other parts of the UI. It also means that you don't have to manually keep records in sync—you can ask for a record by ID and not have to worry about whether other parts of your application have already asked for and loaded it.
One downside to returning a cached record is you may find the state of the data has changed since it was first loaded into the store's identity map. In order to prevent this stale data from being a problem for long, Ember Data will automatically make a request in the background each time a cached record is returned from the store. When the new data comes in, the record is updated, and if there have been changes to the record since the initial render, the template is re-rendered with the new information.
I have a page with a few tables, in total there are a few after 1000 rows.
After the tables is ready, when I click to go on another page, the route is changing in the address bar, but nothing happens until a few seconds.
Then the new page is rendered.
Why is that and what can I do?
This sounds like the new page route you are shifting to has a model hook that takes a bit to load. If that is indeed where your slowdown is then you can add a loading substate to your application to display a loading spinner of some kind.
More details available here: https://guides.emberjs.com/v2.12.0/routing/loading-and-error-substates/
We are building a Sitecore site that will pull in some product data from an external database. On a nightly basis we will query the external database and either Add, Update or Archive/Delete/Remove product content items in Sitecore as needed. Our data template has some fields that will be populated directly from the external database (and will be read-only for content authors) and other fields that they will populate themselves. Included in our custom fields will be the SKU of the item from the external database. It is possible that over time a product could disappear from the external database. In this case we would want Sitecore to somehow remove this item from our list of products, but not completely delete it. The reason for this is that the products that have been removed could reappear in the future and we would not want to lose all of the data that had been added to other custom fields on the item. I can think of a number of different approaches for this:
Use Archiving/Recycling features of Sitecore. When we find that there is a product item in Sitecore that no longer appears in the external database, then we could archive it. That works well. However I can't seem to figure out a way to restore that item later if it reappears in the external database. I don't have any access to any custom fields when an item is archived (from what I have read online). So when I come across a SKU in the external database that is not in Sitecore, I have no way of figuring out if there is an archived item that has that SKU.
Use a custom status field on each product content item. I could set each product content item to "active" or "inactive". This would make it easy to reactivate items that reappear in the external database. However I worry about things like search and publishing. It seems messy to me to have some content items that are inactive in the folder of all products in the master database. It could be confusing to content authors and I worry that they will find their way in to the web database, etc. It seems like I would have to do a lot of custom coding to make sure that those products do not show up on any pages, etc.
When a product disppears from the external database I could then move those content items to a different location in Sitecore. Then when they reappear I could move them back. This also feels messy.
I just wonder if there is some better solution that I am missing. Thanks in advance for any help.
I would go with option 2 "Setting status field on each product "Active" or "Inactive", as its more clear and keep the data in one place.
Additional thing to do (as suggested by Vasiliy) is to set the "Publishable" checkbox on product to "False", this way the product will disappear from web database, hence no extra filter in your search methods.
You can implement custom content editor warning to inform content editor that the current product is "inactive":
Creating Custom Content Editor warnings
Hope this helps
Just a thought what if you just unpublished the items that were removed from the external database and set the ones in the authoring db unpublishable until they reappear again. With this scenario, you could also have a task running archiving items that have been unpublished and not republished for a given period of time.
The best solution really depends on the number and frequency of items appearing / disappearing and the cost benefit of keeping those items in the authoring database vs. deleting them.
We are considering moving from Backbone to Ember. There are a few issues through I can't get answers to from the docs.
1) Ember-Data caches it's data. Our application is multi-user so other users need to be able to see new records created by everyone. Is there a way around this? I read on another post that when a query string is passed, ember data does not cache data, is this true? If it is, can I then just always send query string and nothing will be cached?
2) Ember data has a single model in the router that appears to be instantiated at route load time. I can see that your can request data from multiple sources by returning an object with many this.store.find calls. Say I have a select element and when you select an option, another select gets populated with items based on the first select (which requires a call back to the server). How would that work, how can I get model data on demand (not at route load time)?
I'm not sure if it answers your question but you can always call
model.reload()
to refetch data from server so you can work with up to date data.
You may want to consider Faye (http://faye.jcoglan.com/), which would let you have a pub/sub setup that could update your store by listening to topics of interest. This uses WebSocket for the streaming interface. You could then put new objects into the store, remove or update existing objects which the server could publish to the client.