I'm trying to send by post a json with restangular but this don't return me anything.
Code:
$scope.userPost = {
title: 'foo',
body: 'bar',
userId: 1
}
$scope.registerUser=function(){
$scope.people = Restangular.all('post').post($scope.userPost);
console.log($scope.people);
}
It return me this:
{ "restangularCollection": false, "$object": {} }
http://jsonplaceholder.typicode.com/post 404 (Not Found)
Usually I use this with ajax and it return me a json:
$.ajax('http://jsonplaceholder.typicode.com/posts', {
method: 'POST',
data: {
title: 'foo',
body: 'bar',
userId: 1
}
}).then(function(data) {
console.log(data);
});
Any ideas ?
Restangular works with promises, so, you should be doing something like:
$scope.registerUser = function () {
Restangular.all('post').post($scope.userPost).then((data) => {
$scope.people = data;
console.log($scope.people);
});
}
Or you can take advantage of its enhanced promises and do something like:
$scope.registerUser = function () {
$scope.people = Restangular.all('post').post($scope.userPost).$object;
}
In Angular 4+
constructor(private restangular: Restangular){}
// latter in your method
const baseUsers = this.restangular.all('post');
baseUsers.post({'title':'foo','body': 'bar','userId': '1'})
.subscribe(data => { console.log(data); });
Related
Why second console.log gives me undefined when first one prints actual data? How to assign data received in promise to any variable to be able to use it without promise?
angular.module('dopasujApp')
.controller('productLoader', [ '$scope','getProducts',
function ($scope,getProducts) {
$scope.recived = {};
console.log($scope.list);
function getter() {
return getProducts(1, 150, 20, 'ASC', 'PRODUCT_ID', 'a').then(function (recived) {
$scope.recived = recived;
console.log($scope.recived);
}
);
}
getter();
console.log($scope.recived);
}
]);
Here is my factory code:
angular.module('dopasujApp').factory('getProducts', ['$http', function ($http) {
return function(fit = 1, limit = 150, vendor = 20, sort = 'ASC', orderBy = 'PRODUCT_ID', search='a', size=[], filters={}, attribs=[]) {
var getProduct = {}, recived = {}, APIurl;
getProduct.data={};
getProduct.data.sort=sort;
getProduct.data.orderBy=orderBy;
getProduct.data.search=search;
getProduct.data.filters=filters;
getProduct.data.filters.ATTRIBS=attribs;
getProduct.data.filters.SIZE=size;
recived.list= [];
recived.count = 0;
recived.filters = {};
APIurl = "*******?action=getListing&fit="+fit+"&limit="+limit+"&vendor="+vendor;
var request = $http({
method: "POST",
url: APIurl,
headers: {
'Content-Type': 'application/json'
},
data: {
data: getProduct.data
}
});
var values = request.then(function (response){
return {
list: response.data.QUERY,
count: response.data.COUNT,
filters: response.data.FILTERS
};
});
return values;
}
}]);
Because your getProducts is a promise, and even tough your second console.log is after your getter();, the console.log is executed before your promise is resolved, thats why its undefined.
When I use angular.js, I use $.ajax in methods, then window.location.href when it succeeds. It works.
But when I use vue.js, it doesn't work until I add window.event.returnValue = false; after it.
I think it has nothing to do with angular.js or vue.js, because I use $.ajax, not $http or others. But why doesn't it work when I use vue.js?
$.ajax({
url: 'xxx',
type: 'post',
dataType: 'json',
async : false,
data: {
'xxx' : xxx
},
success: function (response) {
if (response.status == 'success') {
window.location.href = 'xxx';
// window.event.returnValue = false;
}
},
error: function () {
xxx
}
});
Please try this. It work perfectly for me.
created() {
this.vm = #Json.Serialize(Model)
this.ppp = window.location;
this.path = this.ppp.pathname;
this.lastid = this.path.lastIndexOf("/");
this.id = this.path.charAt((this.lastid + 1));
this.url = this.ppp.origin + '/Controller/Action/' + this.id;
console.log(this.url)
axios.get(this.url)
.then(response => { this.summary = response.data });
},
data:
{
vm: [],
summary:[],
ppp:'',
id:0,
url:'',
}
Hope this help
I'm trying to implement an autocomplete feature using Elasticsearch, angularJS and bootstrap.
I've got inspired by this solution :
autocomplete/typeahead angularjs bootstrap on elasticsearch
This is my Angular code:
angular.module('cineAngularApp')
.service('client', function (esFactory) {
return esFactory({
host: 'localhost:9200',
apiVersion: '2.2',
log: 'trace'
});
});
angular.module('cineAngularApp')
.controller('AutocompleteCtrl', function ($scope,client) {
$scope.getResult = function(val){
return client.search({
index: 'autocomplete_test',
fields: 'city',
q: 'city:'+val
}).then(function (resp) {
var keywords = [];
for(var i in resp.hits.hits){
var fields = (resp.hits.hits[i]).fields["city"];
keywords.push(fields);
}
return keywords;
}, function (err) {
console.trace(err.message);
});
};
});
Here is my problem
The above code works fine when I use a simple query, but as soon as I change the query by adding body it doesn't work.
angular.module('cineAngularApp')
.controller('AutocompleteCtrl', function ($scope,client) {
$scope.getResult = function(val){
return client.search({
index: 'autocomplete_test',
fields: 'city',
body: {
query: {
match: {
city: val
}
}
}
}).then(function (resp) {
var keywords = [];
for(var i in resp.hits.hits){
var fields = (resp.hits.hits[i]).fields["city"];
keywords.push(fields);
}
return keywords;
}, function (err) {
console.trace(err.message);
});
};
});
I don't know if it can help but I've also noticed when debugging that it's not a POST request anymore but it's an OPTION one.
Thanks in advance for your help.
Try with this:
return client.search({
index: 'movies',
"fields": [ "title" ],
"body": { // Use body field on elasticsearch client library
"query": {
"query_string": {
"fields": ["title"],
"query": "title:"+val
}
}
}
}).then(function (resp) {
// ....
})
I have just started using $resource to retrieve data and I'm having problems implementing a custom action. The standard GET is using an object ID as follows;
pageContentService.get({ pageId: 1 }, function (data) {
vm.pageContent = data.content;
});
I also want to be able to retrieve the same data using a string as follows;
pageContentService.getByPageName({ pageName: "Home" }, function (data) {
vm.pageContent = data.content;
});
My $resource service is;
(function () {
"use strict";
angular
.module("common.services")
.factory("pageContentService", ["$resource", pageContentService]);
function pageContentService($resource) {
return $resource("/api/pageContent/:pageId", null,
{
"getByPageName": { method: "GET", url: "/api/pageContent/:pageName", isArray: false }
});
};
})();
And I have mocked the backend as follows;
(function (undefined) {
"use strict";
var app = angular.module("pageContentServiceMock", ["ngMockE2E"]);
app.run(function ($httpBackend) {
var content = [
{ "pageId": 0, "pageName": "Unknown", "content": "<h1>Page not found</h1>" },
{ "pageId": 1, "pageName": "Home", "content": '<h1>Home Page</h1>' },
{ "pageId": 2, "pageName": "Programs", "content": '<h1>Programs Page</h1>' }
];
var contentUrl = "/api/pageContent";
$httpBackend.whenGET(contentUrl).respond(content);
var contentById = new RegExp(contentUrl + "/[0-9][0-9]*", '');
$httpBackend.whenGET(contentById).respond(function (method, url, data) {
var pageContent = content[0];
var parameters = url.split("/");
var length = parameters.length;
var pageId = parameters[length - 1];
if (pageId > 0) {
for (var i = 0; i < content.length; i++) {
if (content[i].pageId == pageId) {
pageContent = content[i];
break;
}
}
}
return [200, pageContent, {}];
});
var contentByName = new RegExp(contentUrl + "/[a-z][A-Z]*", '');
$httpBackend.whenGET(contentByName).respond(function (method, url, data) {
var pageContent = content[0];
var parameters = url.split("/");
var length = parameters.length;
var pageName = parameters[length - 1];
if (pageName.length > 0) {
for (var i = 0; i < content.length; i++) {
if (content[i].pageName == pageName) {
pageContent = content[i];
break;
}
}
}
return [200, pageContent, {}];
});
});
})();
The code works as expected when using the "pageId" to return the data however it doesn't appear to execute the "getByPageName" action of the service in the latter code.
From my understanding the custom action is used to extend the existing functionality of the standard $resource methods so I presume I am not implementing it correctly.
You can try with something like this:
angular.module('common.services').factory('pageContentService', ['$resource',
function($resource) {
return {
getByPageName: $resource('/api/pageContent/:pageName', {pageName: '#pageName'}, { method: "GET", isArray: false }),
getByPageId: $resource('/api/pageContent/:id', {id: '#id'}, { method: "GET", isArray: false })
};
}
]);
And after injecting pageContentService in a controller you can retrieve your data by:
pageContentService.getByPageName({ pageName: "Home" }, function (data) {
vm.pageContent = data.content;
});
Or:
pageContentService.getByPageId({ id: 1 }, function (data) {
vm.pageContent = data.content;
});
The problem turned out to be in the mocking. I was using;
var contentByName = new RegExp(contentUrl + "/[a-z][A-Z]*", '');
When I should have been using;
var contentByName = new RegExp(contentUrl + "/[a-zA-Z]+", '');
Once I fixed that I could use either;
pageContentService.get({ pageId: 1 }, function (data) {
vm.pageContent = data.content;
});
To retrieve the data using the default "GET" or;
pageContentService.getByPageName({ pageName: "Home" }, function (data) {
vm.pageContent = data.content;
});
To use the custom action. I also tried Michelem's suggestion using;
function pageContentService($resource) {
return {
"getByPageId": $resource('/api/pageContent/:pageId', null, { method: "GET", isArray: false }),
"getByPageName": $resource('/api/pageContent/:pageName', null, { method: "GET", isArray: false })
};
}
But I couldn't get this to work.
I have few resources written on AngularJS that access a Tastypie API. Everything works fine, except for a detail: tastypie always encapsulate the actual result inside a objects attribute on a JSON, example:
/api/v1/reminder/:
{
meta: {
limit: 20,
next: null,
offset: 0,
previous: null,
total_count: 3
},
objects: [{
category: {
color: "#999999",
id: 1,
name: "Groceries",
resource_uri: "/api/v1/category/1"
},
description: "",
due_date: "2010-10-16",
id: 1,
repeat: "weekly",
resource_uri: "/api/v1/reminder/1",
value: "-50"
}, {
category: {
color: "#999999",
id: 1,
name: "Groceries",
resource_uri: "/api/v1/category/1"
},
description: "",
due_date: "2010-10-17",
id: 2,
repeat: "weekly",
resource_uri: "/api/v1/reminder/2",
value: "-50"
}
}
It was wasy to fix using a callback to the get() call:
Reminder.get().$then(function (result) {
$scope.reminders = result.data.objects;
});
But I know result.resource is an actual Reminder instance.
.factory('Reminder', ['$resource', function($resource){
var Reminder = $resource('/api/v1/reminder/:id', {}, {
get: {
method: 'GET',
isArray: false
}
});
Reminder.prototype.TESTE = function () {console.log('asd');};
return Reminder;
}])
Now I need to implement behavior on my Reminder class, and I need every element on my meta.objects to be an instance of Reminder:
Reminder.get().$then(function (result) {
$scope.reminders = result.data.objects;
result.resource.TESTE(); // -> outputs 'asd'
o = result.data.objects[0];
o.TESTE // -> undefined, obvisously
i = new Reminder(o);
i.TESTE() // -> outputs 'asd'
});
So, how to I get angularjs to understand that every object on objects is the actual result so it behaves like a list of instances?
The workaround is to creating a new list iterating on the results creating the instances, but it's not optimal...
Suggestions?
Solution by #rtcherry:
As suggested by rtcherry, I used restangular
Configuring the reading of request data:
.config(['RestangularProvider', function(RestangularProvider) {
RestangularProvider.setBaseUrl("/api/v1");
RestangularProvider.setResponseExtractor(function(response, operation, what, url) {
var newResponse;
if (operation === "getList") {
newResponse = response.objects;
newResponse.metadata = response.meta;
} else {
newResponse = response.data;
}
return newResponse;
});
}])
Loading the reminders:
function RemindersCtrl ($scope, $rootScope, Reminder) {
$scope.reminders = Reminder.getList();
}
Adding my custom method to Reminder (not as clean as ngResource, but doable):
.factory('Reminder', ['Restangular', '$filter', function(Restangular, $filter){
var Reminder = Restangular.all('reminder');
var remainingDays = function () {
//do stuff
};
// adding custom behavior
Restangular.addElementTransformer('reminder', false, function (reminder) {
reminder.remainingDays = remainingDays;
return reminder;
});
return Reminder;
}])
Solution by #moderndegree:
I used pure ngResource:
var tastypieDataTransformer = function ($http) {
return $http.defaults.transformResponse.concat([
function (data, headersGetter) {
var result = data.objects;
result.meta = data.meta;
return result;
}
])
};
...
.factory('Reminder', ['$resource', '$http', function($resource, $http){
var Reminder = $resource('/api/v1/reminder/:id', {}, {
query: {
method: 'GET',
isArray: true,
transformResponse: tastypieDataTransformer($http)
}
});
Reminder.prototype.remainingDays = function () {
// doing stuff
};
return Reminder;
}])
My controller:
Transaction.query(filter).$then(function (result) {
$scope.days = [];
var transactions = result.resource;
resource[0].remainingDays(); // it works
});
If you wanted to avoid using an additional library, you should be able to do the following:
$resource('/api/v1/reminder/', {}, {
query: {
method: 'GET',
isArray: true,
transformResponse: $http.defaults.transformResponse.concat([
function (data, headersGetter) {
return data.objects;
}
])
}
});
This will append your transform to $HttpProvider's default transformer.
Note: Correct me if I'm wrong on this one but I believe this feature requires v1.1.2 or greater.
You may want to try something like restangular.
There is some configuration needed to make that work. An example is here.
I ended up doing the following in order to preserve the meta object directly on the results returned by Reminder.query() (expanding on the answer from #moderndegree).
var Reminder = $resource('/api/v1/reminder/', {}, {
query: {
method: 'GET',
isArray: true,
transformResponse: $http.defaults.transformResponse.concat([
function (data, headersGetter) {
return data.objects;
}
]),
interceptor: {
response: function(response) {
response.resource.meta = response.data.meta;
}
}
}
});
That allows you to get the meta value directly on the returned object:
var reminders = Reminder.query(...);
console.log(reminders.meta); // Returns `meta` as expected.
I think it would also be possible to do something similar inside the callback from Reminder.query since the response object is available there as well.