Reputation: 1926
I have a Loopback API with an Angular front end, and have been seeing some strange behavior when trying to call a non-static remote method.
I've boiled it down to this example. When making a call like this:
$scope.myInstance = MyModel.findOne({}, function success(value){
$scope.greeting = value.$prototype$hello({}, function success(){});
});
I'm finding that $scope.myInstance ends up containing the result of the call to $prototype$hello and $scope.greeting is empty. MyModel is defined with a remote call like this:
module.exports = function(MyModel) {
MyModel.prototype.hello = function(cb) {
cb(null,"Hello: " + this.name);
}
MyModel.remoteMethod(
'hello',
{
isStatic: false,
http: { verb: 'get' },
returns: {arg: 'message', type: 'string'}
}
);
};
So if I have this in my template:
Greeting = {{ greeting }}, Instance = {{ myInstance }}
I see:
Greeting = {}, Instance = {"message":"Hello: Test","$promise":{},"$resolved":true}
With the greeting result clearly in place of the model instance. I would expect to see the model instance in the Instance variable:
Greeting = {}, Instance = Instance = {"name":"Test","id":1,"$promise":{},"$resolved":true}
There is a brief flash of the model during loading.
I can work around this by retrieving additional throwaway instances of the model, but I'm hoping someone knows why this is happening and if there's a cleaner solution.
UPDATE 08/12/2015: I've created a Plunker to demonstrate this problem here, but this only contains the client-side JS. For the full loopback project, I've added the code to a GitHub repo
Interestingly enough, the behavior is slightly different under Safari, which doesn't render the instance at all:
Greeting = {}, Instance =
The originally described behavior was seen under Chrome.
Upvotes: 0
Views: 839
Reputation: 1340
I checked your plunker, and I think I got the issue here, your code is:
$scope.myInstance = MyModel.findOne({}, function success(value){
$scope.greeting = value.$prototype$hello({}, function success(){});
});
let's forget about the success function for a second, findone()
function returns your requested document from a mongodb, as I think, which means, naturally, the returned document or query will be stored in $scope.myInstance
, which is how your app is behaving.
Now for the success function, it's trying to call value.$prototype$hello
which doesn't exist in the response object (value), so the value is undefined
and that gets stored in the $scope.greeting
that's why it is displaying as empty.
why $prototype$hello
is undefined
is simple, it's a prototype object if it was a part of your app but you are trying to access this function through a response object that doesn't have it.
I hope this answers your question
the problem is with this line
$scope.greeting = value.$prototype$hello({}, function success(){});
just make like this:
value.$prototype$hello({}, function success(val){$scope.greeting = val.message;},function error(err){console.log(err);});
change your code to be like this:
ModelA.findOne({}, function success(value){
//debugger;
value.$prototype$hello({}, function success(val){$scope.greeting = val.message;},function error(err){console.log(err);});
}).$promise.then(function(res) {
$scope.myInstance = res;
});
this way, you will not have bogus data in your variable before the promise is resolved. And, it's purely normal for the response object to have $promise, and $resolved attributes, because it's a resource promise object
now after you clarified the issue on your last comment, I was able to understand it, I was looking for something else, but anyway they are related. what was happening is a conflict, you are doing two async calls, you should treat them that way, this is how the code should be:
ModelA.findOne({}).$promise.then(function(value) {
$scope.myInstance = value;
var v2 = angular.copy(value);
v2.$prototype$hello({},
function (val){
$scope.greeting = val.message;
},
function (err){console.log(err);}
);
});
let me know if you need more input regarding the code
Upvotes: 1