Angular update from service and id issues - angularjs

I’ve been following the Scotch.io tutorial of using Stamplay and Angular to build an Etsy clone from here https://scotch.io/tutorials/build-an-etsy-clone-with-angular-and-stamplay-part-1
I have been trying to update a record. I have a service with the following function:
function update(id, data) {
var def = $q.defer();
// instantiate a new product model from the stamplay js sdk
var product = new $stamplay.Cobject(‘product’).Model;
product.fetch(id)
.then(function() {
// loop over the fields in data and update the product
angular.forEach(data, function(value, key) {
product.set(key, value);
});
return product.save();
})
.then(function() {
// return the record
def.resolve(product);
});
return def.promise;
}
Then in my actual controller I have another function to connect to the service and do the update:
function update() {
Product.update(main.productData)
.then(function (data) {
main.successMessage = 'Record Updated!';
});
}
The issue is i don’t get an id, even though the function does/should fetch the id.
The error i get is
[Error] Failed to load resource: the server responded with a status of 400 (Bad Request) ([object Object], line 0)
and the url its going to is
/api/cobject/v1/prdouct/[object%20Object]
obviously not getting the id.
Any ideas are appreciated.

The update method takes two parameters and you only supply it with one

Related

not able to push the data in to the list

I have one list which contains list of objects so, now i want to add one more object to the each list in the main list
I am using AngularJS
here is the code which i tried
$scope.mediaList = [];
$scope.getTheProfile = function(data){
for(var i in data)
{
ProfileService.getByHandle(data[i].handle,function(profiledata)
{
$scope.mediaList[i].displayName = profiledata.name.displayName
},
function(data , status){
console.log("In Error");
if(status == '400'){
$scope.errors.push(data["ERROR"])
}
},
function(data , status){
console.log("In forbidden")
})
}
alert($scope.mediaList[0].displayName)
}
so i am trying to add displayName to that list
now the problem is i am not able to get the value in that alert
if that alert is inside ProfileService.getByHandle function then i am getting the value
this is the function getByHandle
this.getByHandle = function(handle, successCB, errorCB, forbiddenCB) {
console.log("In Profile Service for fetching the profile by handle: "+handle);
HttpCommunicationUtil.doGet(apiConstants["profile"]["getByHandle"]+"/"+handle, successCB, errorCB, forbiddenCB);
};
Looking at getByHandle, it seems you are making asynchronous HTTP request using HttpCommunicationUtil.doGet.
What happens is this: for loop will make the HTTP calls and trigger this alert alert($scope.mediaList[0].displayName) without waiting for the response of getByHandle, as it's an asynchronous request.
Therefore, when you try to alert there will be an empty array [] value for $scope.mediaList due to line#1. So $scope.mediaList[0].displayName will produce error saying unable to get displayName of undefined.
You can return promises in ProfileService.getByHandleand when it's resolved use .then to update your variable.
If you can post code for HttpCommunicationUtil.doGet it'll be more useful.
EDIT:
Without HttpCommunicationUtil.doGet, I'll give you an idea of how to do it in a generic way.
Service:
this.getByHandle : function(params) {
return $http.get('/api/endpoint');
}
Controller:
ProfileService.getByHandle(params).then(function(data){
//use data to push response in $scope.mediaList[i]
});

BreezeJs loading metadata 5 times on the page, trying to use fetchMetaData but it errors

I am trying to get the metadata before I perform any queries on the page, because each query is trying to get the metadata for a total of 5 times and the page is very slow. I am hoping this helps.
//version info:
var breeze = {
version: "1.5.4",
metadataVersion: "1.0.5"
};
Howevever I am getting this error:
manager.fetchMetadata(...).then(...).fail is not a function
Here is the code sample:
var manager = emProvider.createManager();
function getMetaData()
{
var deferred = $q.defer();
manager.fetchMetadata()
.then(function (data, status) {
deferred.resolve(data);
console.log('manager.fetchMetadata() success');
})
.fail(function (data, status) {
deferred.reject(data);
console.log('manager.fetchMetadata() reject');
});
return deferred.promise;
}
THis is what the createManager function looks like from the injected 'emProvider' service.
var masterManager = new breeze.EntityManager(serviceRoot + 'odata/');
// private function to create a new manager
function createManager() {
var manager = masterManager.createEmptyCopy(); // same configuration; no entities in cache.
// ... copy in some entities (e.g.,picklists) from masterManager
return manager;
}
try the following... surround all of your code blocks with anonymous self-invoking functions except for the master manager creation, comment out the getMetaData function, be sure to pick up the right adapter for your service... breeze odata configuration , make sure Q is on your js bundle at the top of your page.
breeze.config.initializeAdapterInstance("dataService", "odata");
var masterManager = new breeze.EntityManager(serviceRoot + 'odata/');
(function () {
var op = breeze.FilterQueryOp;
var query = null;
query = new breeze.EntityQuery()...
...all of your other breeze code...
masterManager.executeQuery(query).then(function (data) {...
})();
If you are using $q from AngularJS, you should use .catch instead of .fail. AngularJS uses .catch for errors in promises.

angular $resource receive extra information

I am using ng-resource to do ajax request. I want to send extra info besides the data.
For example, I have an article entity on my server
exports.fetchArticle = function(req, res, next) {
var article = req.article
return res.json({data: article, message: 'success fetch article'})
}
The reason I wrap it is that, in the case of deletion, it makes no sense to send data, I can just return res.json({data: null, message: 'deleted successfully'})
on my client side, I have:
$scope.fetchArticle = function() {
Article.get({articleId: $routeParams.articleId}, function(response) {
$scope.article = response.data
$scope.ajaxSuccess = response.message
}, function(err) {
$scope.ajaxError = err.data.message
})
}
$scope.article is not an instance of ng-resource anymore, thus I can't do further request with $scope.article, i.e. this will cause error, since $scope.article is a plain json object:
$scope.article.$update(function(response) {...})
If I simply return res.json(article) from server, it works, but I can't send along the message.
The reason I dont generate the message from client but fetch from server is that, the error message is from server, I want to keep success message consistent with the error message.
Is there any other elegant way to send the message?
Assuming that all your servers responses follow this format:
{
data: {/*...*/},
message: 'some message'
}
You could use $http's transformResponse for that, so that you get an ngResource instance that is your returned object while still processing your message. For that, you need a transform-function:
function processMessage(data, message) {
//Do whatever you want with your message here, like displaying it
}
function transform(response) {
processMessage(response.data,response.message);
var data = response.data;
delete response.data;
delete response.message;
for(var attributeName in data) {
response[attributeName] = data[attributeName];
}
return response;
}
Then you can add this function to $http's default transfroms in the config of your app:
angular.module("yourApp",[/* ... */])
.config(function($httpProvider){
//....all your other config
$httpProvider.defaults.transformResponse.unshift(transform);
});
Now all repsonses from $http get transformed by this function, triggering processMessage and leaving you with a ngResource instance of the returned object.

AngularJS : Service for data between controllers

I have a page with a main controller and a nested controller for showing details about a product. I want to use a a service in angular to call the server, retrieve a data object and hold that data object. The main controller will call the service to fetch the data and the details controller needs to know it was updated and then access the data. My service looks like this:
.service("productService", function ($http, $q) {
var product = {};
//interface that is returned
return ({
fetchProduct: fetchProduct,
clearProduct: clearProduct,
product: product
});
function fetchProduct(ID) {
var request = $http({
method: "get",
url: "/online/productdata.ashx?itemID=" + ID,
params: {
action: "get"
}
});
return (request.then(handleSuccess, handleError));
};
function clearProduct() {
product = {};
};
// Transform the error response, unwrapping the application dta from
// the API response payload.
function handleError(response) {
// The API response from the server should be returned in a
// nomralized format. However, if the request was not handled by the
// server (or what not handles properly - ex. server error), then we
// may have to normalize it on our end, as best we can.
if (
!angular.isObject(response.data) ||
!response.data.message
) {
return ($q.reject("An unknown error occurred."));
}
// Otherwise, use expected error message.
return ($q.reject(response.data.message));
};
// I attempt to transform the successful response and unwrap the application data
// from the API response payload.
function handleSuccess(response) {
product = response.data;
console.log("Found Data: " + angular.toJson(response.data))
return (response.data);
};
})
In my main controller I set a scope object to the service like this:
$scope.SelectedProduct = productService;
When the user clicks the button to show the product it is called via the $scope handle:
$scope.SelectedProduct.fetchProduct(ID);
The details controller has the same assignment for the $scope.SelectedProduct. I am new to using services but what I understood is that angular would bind to the service object and changes to the property product would trigger binding to any updates. That is not happening - in fact I do see the data after the fetch operation. In the service I have a console.log on the returned data and it is showing the correct data. However the product property is not getting updated. Can someone tell me what I am doing wrong please? Neither controller has access to the data after it is fetched. I understand that I am getting back a promise but the data is never there even after a timeout check.
Try it with a factory instead of a service.
AngularJS: Factory vs Service vs Provider

Get _id of new Kinvey data on angular app

When I save new data to a DataStore in Angular, I don't want to specify the _id. The system automatically assigns one. From looking at the network trace, the _id is passed back to the application in the response - https://baas.kinvey.com/appdata/appxxx/activities/54ac3d8671e2d7933b0116b4 - but I don't see anyway of finding that in the Angular documentation about how to retrieve that _id so I can add it to an existing list or do other processing.
var promise = $kinvey.DataStore.save('activities', {
text : $scope.newActivity.text ,
duedate : '2015-01-01'
});
promise.then(
function () {
$scope.newActivity.text = '';
},
function (error) {
//Kinvey insert finished with error
alert("Error insert: " + JSON.stringify(error));
});
Kinvey will actually return the object to you in the promise, and you can just grab the _id off the returned object.
promise.then(function(data) {
// Here's where you get your _id
$scope.newActivity.text = data._id;
}, function(err) {
console.error(err);
});

Resources