Initializing StateNotifier Provider to return list of products to a feeds screen - state

I have tried several suggestions and rewritten my code to get past errors. But now only a blank screen (no list of products) being returned on navigation. Here are screenshots of the 2 critical screens (the productController and the feeds screen.

The goal of a StateNotifier is to hold a state, so in your super constructor you are using a empty array if state (optional positional parameter of ProductNotifier) is null.
You are not assigning your products to the state.
As your products are hardcode, you can either pass them as the initial state:
...
(ref) => ProductNotifier(products); // products is your List<Product>
...
or
class ProductNotifier extends StateNotifier<List<Product>> {
ProductNotifier() : super(products); // products is your List<Product>
...

Thanks to Juan Carlos for reminding me that StateNotifier keeps app state. After a restful and second reflection, I changed products to state in my getter statement and keeping the original code. Everything now works as expected. I am ready to implement API data fetch from Firestore now that the static hardcoded data acts as expected. It served its purpose as a placeholder. Thanks a bunch.

Related

Ember data store handling array of objects

I'm new to ember and exploring its capabilities by building a small module. I came across a scenario where I need to update the ember model content synchronously. The ember-data model contains an array of objects as contents.
I was hoping to perform a few tasks as follows
Perform an array content reorder - for the sake of simplicity we
can assume swapping the first and last item.
Append a record
without a network call
Delete a record without a network call.
Doing these should automatically sync the data bindings/computed props
My data model after a peekAll call contains 10 records(shown below) on which I need to perform the above operations.
My model is as shown below
export default Model.extend({
testId: attr('number'),
name: attr('string')
});
What is the right approach to update the content record? Could someone please suggest how to proceed?
This looks to me like the results of running something like let arr = await store.findAll('test-model'), is that correct? This is probably a PromiseArray and you can access the data as a Javascript Array by calling arr.slice() on it. This will let you do normal array operations, though performing a content re-order doesn't really make much sense in this scenario. I assume you were using it as an example.
For adding and removing records without a network call you can do that by going back to the store and this is what is covered in the docs, you don't need to act on this Object you're looking at.
Adding a new record:
let testModel = store.createRecord('test-model', {
name: 'Lorem ipsum'
});
testModel.save(); //until you do this no network data will be sent
Removing a record:
let testModel = store.peekRecord('testModel', 1); //to get a record with ID of 1
testModel.deleteRecord();
testModel.save(); //until you run save no network is sent
Once you've taken action like this on the store the data structure you posted above may be updated to contain the new data depending on how you accessed it originally. You can also re-fetch data from the store which will now know about your adding a deleting of models (even though you haven't saved it back to the server yet)
If you haven't saved yet and you re-do a peekRecord you'll need to filter out any deleted records from the results.
let undeletedModels = this.store.peekAll('test-model').filter(m => !m.isDeleted);

Ember store.findAll is reloading view and store.query is not

At the moment, when an article is added to the store, my view is not updated when I use store.query(), filtering server side, in my route but it's updated when I use store.findAll() with filtering client side.
With findAll, filtering client side
//route.js
model() {
return this.get('store').findAll('article');
}
//controller.js
articleSorted: computed.filterBy('model', 'isPublished', true),
and with query filtering server side
//route.js
model() {
return this.get('store').query('article', { q: 'isPublished' }),
}
The fact is that findAll is reloading and query is not.
I've found this but did not understand
https://github.com/emberjs/ember.js/issues/15256
thanks for the question. I'll try to answer it the best I can but it would seem like some more documentation should be added to the Ember Guides to explain this situation 🤔
Essentially this.store.findAll() and this.store.query() do two very different things. findAll() is designed to be a representation of all of the entities (articles in your case) so it makes sense that the result will automatically update as the store finds more articles it should care about. It does this because it doesn't return an array of articles, it returns a DS.RecordArray that will automatically update.
query() on the other hand is designed to ask the backend every time what it expects the result to be, and you are usually passing a number of parameters to the query() call that the backend is using to find or filter results. It would be impossible for the frontend to know exactly how the backend interprets these query parameters so it is not possible for it to "auto-update" when a new article is added that would satisfy the same query.
Does that make sense? Would you like me to go into any more detail?
When using store.query to fetch data from the server, the view can still be auto-updated with new client-created store data before it's saved to the server, by using a "live" record array for it.
While data from store.query isn't live, data from store.peekAll is, so you can query first but then leverage store.peekAll for display. You can query before setting your model to the peeked data, or keep your query as the model but use some other property of peeked data for display. The important part is to ensure the query is resolved before peeking at the store.
Example based on the current code in your question:
// route.js
beforeModel() {
// using return ensures this hook waits for the promise to resolve before moving on
return this.store.query('article', { q: 'isPublished' });
}
model() {
// Queried server data should now be available to peek at locally,
// so we can set the model to a live version of it. Don't append filterBy here,
// otherwise it will no longer be live.
return this.store.peekAll('article');
}
// controller.js
// seemingly redundant filter since using query, but needed if there are other records
// in the store that shouldn't be displayed, and is recomputed when
// a record is added or removed from the store-based model
articleSorted: filterBy('model', 'isPublished', true) // filterBy imported from '#ember/object/computed'
// template.hbs
{{#each articleSorted as |article|}}
{{!-- this displayed list should update as new records are added to the store --}}
{{article}}
{{/each}}
Note that after a new record is saved to the server, the query can be updated via its update method or via a route refresh. This will re-run the query and get the updated results from the server. If the query is the model, that would look like model.update(). If it was saved to someOtherProperty, then someOtherProperty.update(). In either case, route.refresh() could be used instead to re-run all route hooks.
Some specific comments/examples that I think are helpful:
https://github.com/emberjs/ember.js/issues/15256#issuecomment-302894768
https://github.com/emberjs/ember.js/issues/15256#issuecomment-302906077
https://github.com/pouchdb-community/ember-pouch/issues/232#issuecomment-428927114

PowerApps: Filter by user no delegation

Need some help with PowerApps - I am trying to filter the gallery where the Person column (ROMEmail) equals the logged in user.
This code is working, but the blue circle of death comes up - whilst in test at the moment, i dont have over 500 records, but will do within a month of trialling this
Any ideas on how to workaround this? Using a collection or variable perhaps? I haven't really used these yet so a detailed resolution would be greatly appreciated.
SortByColumns(Filter('Reviews', StartsWith(LocationName, TextSearchBox1.Text),ROMEmail.Email = User().Email), "Modified", If(SortDescending1, Descending, Ascending))
A collection would be your best choice.
To add a collection in your app replace the code where you grab your data by something like this:
ClearCollect(localData,'Reviews')
This collects all the data in a locally collection. The ClearCollect replaces all your data by the new ones.
After this you can sort and filter directly on your collection. For example in a gallery. Using your code it would look like this:
SortByColumns(Filter(localData, StartsWith(LocationName, TextSearchBox1.Text),ROMEmail.Email = User().Email), "Modified", If(SortDescending1, Descending, Ascending))

Cant retrieve local records from store using Ember Data

I am trying to retrieve records which have already been loaded into the store by using this line in a controller:
var allProducts = this.store.all('product');
However, this is returning a strange object (see screenshot). When I call length on it, the result is "undefined." I have used the Chrome Ember inspector to confirm that records have indeed been loaded into Product before the above line of code is run. I thought since store.all returns a recordarray I could iterate over it immediately unlike a promise. Where am I going wrong please?
The strange object that is returned is a record array. This is important so that Ember can set up observers for arrays that are loaded. I believe this is what is causing your confusion. See more specifics in the docs:
It's important to note that DS.RecordArray is not a JavaScript array.
It is an object that implements Ember.Enumerable. This is important
because, for example, if you want to retrieve records by index, the []
notation will not work--you'll have to use objectAt(index) instead.
You will have to look at the documention for DS.RecordArray but you should be able to iterate over it using the forEach method. See the ember array documentation for more details.
The issue was that I was trying to iterate over the recordarray using a traditional for loop. Seems that a) recordarray cannot return length and 2) one must use a forEach loop to iterate over it, which is what I had initially did but dropped because forEach does not support break or continue.
Ahh promises! :)
You should be able to do this:
var allProducts = this.store.all('product').then(function(products) {
return products;
});

How do you get child bands in ultragrid without using related tables in a dataset?

I'm using linq to pull back an object (i.e. customer) that might have a collection of other objects(customer.orders). I would be nice if I can pass this list of customers to the ultragrid and a hierarchical view of customers and thier orders displayed on databind. When I try this, I just get customers. Anyone know how to get this to work with non dataset objects?
Figured it out. IList collection works and will create bands for properties of your domain object if it is an IList<T>. Just make sure thatDisplayLayout.ViewStyle = ViewStyle.MultiBand.
I've tried the following and it didn't work:
DisplayLayout.ViewStyle = ViewStyle.MultiBand
I read from this blog that it must be List and not IList in order to work, and it did.
We work with our own custom datasource for grid, so we first create a structure of bands and then we initialize data OnDemand, handling events
InitializeDataRow
InitializeRowsCollection
CellDataRequested
We use Tags to navigate through the structure.