obtain the result or HTTP response of an add operation of ngrx/data - angular-ngrx-data

As described in the entity dataservice documentation , the add operation expects an entity to be saved on the backend. What it doesn't say is that it expects the created entity to be returned from the backend (with an ID etc). My backend does that and it works as expected, however
when I tap into the add operation, which returns an Observable, at least my IDE gives me Observable methods to continue... it's best demonstrated with a piece of code
this.myEntityService.add(myNewEntity).pipe(
tap(data => console.log('data:', data))
)
Nothing is logged to the console at all.
My question is, how do I get what's returned from the HTTP service? e.g. the entity, persisted to the backend database?

The problem was, I didn't subscribe to the Observable that add returns.
I assumed the data is being emitted regardless of a subscription.
So the correct way to receive the result is
this.myEntityService.add(myNewEntity).subscribe(data => {
console.log('data:', data);
});
subscribing to it.

Related

Load all documents at once. Not progressively

When I run a .fetch() command, it first returns null, then say suppose I have 100 documents and it will keep on loading from 1 to 100 and the counter keeps updating from 1 to 100 progressively. I don't want that to happen. I want all the results to be displayed at once after the fetch process has been completed.
Also, how can I display a relevant message to the user if no documents exist? The fetch method doesn't work for me since it returns 0 at first and hence "No document found" flashes for a second.
dbName.find({userID:"234234"}).fetch()
Even though the above has 100 docs, it first shows null and then keep loading the documents one by one. I want it load all at once or just return something if no docs exist.
I don't want that to happen. I want all the results to be displayed at once after the fetch process has been completed
To really obtain all documents at once on the client you will have to write a Meteor Method that returns all the documents:
Meteor.methods({
'allDocs' () {
return dbName.find({userID:"234234"}).fetch()
}
})
Note, that you have to call fetch on the cursor to return the documents, otherwise you will face an "unhandled promise rejection error".
Then call it from the client as usually. You can even add the documents to your client side local collection without affecting allow/deny (which should be off / deny all by default):
Meteor.call('allDocs', (err, documents) => {
// ... handle err
// all client collections have a local collection accessible via ._collection
const localCollection = dbName._collection
documents.forEach(doc => localCollection.insert(doc))
})
Advantages:
Returns all documents immediately
Less resources consumed (no publication observers required)
Works with caching tools, such as ground:db, to create offline-first applications
Disadvantages:
You should limit the query and access to your collections using Methods as much as possible, (using mdg:validated-method) which can require much more effort than shown in this examples
Not reactive! If you need reactivity on the client you need to include Tracker and reactive data-sources (ReactiveVar etc.) to provide some decent reactive user experience
Manual syncing can become frustrating and is error prone
Your question is actually about the subscription and it's state of readiness. While it is not yet ready, you can show a loading page, and once it is you can run the .fetch() to get the whole array. This logic could be put in your withTracker call, e.g.:
export default withTracker((props) => {
const sub = Meteor.subscribe('users');
return {
ready: sub.ready(),
users: sub.ready() && Users.find({userID: props.userID}).fetch()
};
})(UserComponent);
Then, in your component, you can decide whether to render a spinner (while ready == false), or the users.
Your question is not entirely clear to me in terms of tools etc (please state which database connector lib are you using), but firstly, given you're doing a database access, most likely, your ".fetch()" call is not a sync function but async, and also most likely, handled by a promise.
Secondly, given that you're using react, you want to set a new state only after you get all the results back.
If fetch is a promise then just do:
dbName.find({userID:"234234"}).fetch().then(results =>
setState({elements:results.data}) // do your processing accordingly
}
By only calling setState inside the promise, you'll always have all the results fetched at that instant and only with that do you update your component state with the setState function - either using your react component class this.setState or with hooks like useState (much cleaner).

What is the difference between .all() and .one() in Restangular?

What is the difference between these two? Both seems to make a GET to /users and retrieve them.
Restangular.one('users').getList().then(function(users) {
// do something with users
});
Restangular.all('users').getList().then(function(users) {
// do something with users
});
I understand that you can do one('users', 123) and it will retrieve /users/123 but without the second argument it seems to be the same thing. Why not just have one method in that case?
The one() function has a second argument that accepts an id e.g. .one('users', 1).
one('users', 1).get() translates to /users/1
all('users').getList() translates to /users
Unlike all(), one() is not generally used with .getList() without argument. However, if you were to call .one('users', 1).getList('emails') or .one('users', 1).all('emails').getList(), then you would make a GET request to /users/1/emails.
My guess is that they are there for expressing an intention of what you are going to do. I would understand those as a way to build the url, expressing if you are accessing to the whole resource or to a specific one.
In the end, they are gonna build and do a GET request but because you do a GET and retrieve some data it does not mean that it should be used in that way.
Example extracted from https://github.com/mgonto/restangular/issues/450
getList can be called both ways. If it's called in an element one,
then it needs a subelement to get to a Collection. Otherwise, it
fetches the collection. So the following is the same:
Restangular.one('places', 123).getList('venues') // GET /places/123/venues
Restangular.one('places', 123).all('venues').getList() // GET /places/123/venues
As you can see, it is more expressive to call one('places', 123).all('venues') to understand that you just want the venues located in the area/place 123.
Maybe the following url will help you:
https://github.com/mgonto/restangular/issues/450
I've recently discovered a difference between these methods. Yes, both of them make the same get requests, but the results you get might surprise you (as they surprised me).
Let's assume we have an API method /users which returns not strictly an array, but something like this:
{
"result": [{...}]
}
So an array is returned as a value of some prop of the response object. In this case get() and getList() work differently. This code works well:
Restangular.get('users').then(function (response) {...});
Your response handler gets invoked after response has been received. But this code doesn't seem to work:
Restangular.all('users').getList().then(function (response) {...});
Response handler is not invoked, despite that request completed with status code 200 and non-empty response. Browser console doesn't show any errors and network monitor shows successful request.
I've tested this with Restangular 1.5.2 so probably this is already fixed in newer versions.

Server Response to a Delete Request in Backbone

I'm still pretty new to Backbone and I've been trying to find an answer to this for a bit:
So, I know for the first 3 types of CRUD requests (Create, Read and Update) that you have the server return the JSON for a model. What I wanted to know is do you do the same for Delete?
You DO need to respond with JSON. A common practice is just to return a simple JSON object with a message. (It doesn't need to be the data for the model destroyed). Consider responding with:
{ message: "Model successfully destroyed!" }

what is a Backbone model.save( ) call expecting on a POST operation?

I'm calling save() on a backbone model to do a POST operation on the back-end. The operation completes successfully server-side (I can see the record added and the response status comes back as 200). Currently the RESTful api call is returning the ID of the inserted record in the response body. I have success and error callbacks defined that I pass to the save call, but success is never called. Instead, the Backbone code is choking on that ID that gets returned from the REST call. Is there a better way for me to handle this from the client end or should the REST api implementation be returning something else?
By default I believe it expects the changed properties of the object as JSON. See: http://documentcloud.github.com/backbone/#Sync

RIA: Loading entity sets

I am missing something very fundamental when working with SL4 RIA entities.
I have a Domain Service with User entities. On the service context, I have a method:
EntityQuery<User> GetUsersQuery()
I perform a load like so:
context.Load(context.GetUsersQuery(), (loadOp)=>
{
// Things done when the load is completed
}, null);
When the Completed action executes, the loadOp.Entities collection is full of the User entities, but they are not attached to the context.Users entity set. It also appears that I can't attach them manually from the callback. What important step am I missing to get these tracked in the entity set?
Just to elaborate, in the completed handler, I tried:
foreach (var user in loadOp.Entities)
context.Users.Attach(user);
And I get an exception that says an entity with that name is already attached.
Yet, both context.Users and context.EntityContainer are empty.
Are you sure you are using the same instance of the context in all cases? What does context.EntityContainer.GetEntitySet<User>().Count say?
Does LoadOperation<User>.HasError return true? If so, what is the error?

Resources