p.then is not a function, error with angular parser? - javascript

I have the next Json:
[{
"given": "given3",
"when": "when3",
"then": "then asjdh"
}, {
"given": "given1",
"when": "when1",
"then": "then asjdh"
}, {
"given": "given2",
"when": "when2",
"then": "then asjdh"
}]
and when I try to do:
<ul class="phones">
<li ng-repeat="behavior in behaviors" >
<p>GIVEN: {{behavior.given}}</p>
<p>WHEN: {{behavior.when}}</p>
<p>THEN: {{behavior.then}}</p>
</li>
</ul>
I have the next error:
Error: p.then is not a function
anonymous#file:/~/app/lib/angular/angular.js:6531
lex/readIdent/token.fn<#file:/~/app/lib/angular/angular.js:5914
$interpolate/fn#file:/~/app/lib/angular/angular.js:4931
Scope.prototype.$digest#file:/~/app/lib/angular/angular.js:7889
Scope.prototype.$apply#file:/~/app/lib/angular/angular.js:8097
done#file:/~/app/lib/angular/angular.js:9111
completeRequest#file:/~/app/lib/angular/angular.js:9274
createHttpBackend/</xhr.onreadystatechange#file:/~/app/lib/angular/angular.js:9245
"
well i don't understand so much about how angular parse the information in json, but i think "then" is a reserved word, or something like that?
Any suggestion?

The problem is that then is used in the promise API and you are using it as a data key for your model. It sees that "then" is defined and tries to execute it, but then is a string, not a function.
Promise API

well... i solved using a simple replace in the controller.
/* Controllers */
function behaveListCtrl($scope, $http) {
$http.get('behaveMe/behaves.json').success(function(data) {
for(var i in data){
data[i].Then = data[i].then;
delete data[i].then;
}
$scope.behaviors = data;
});
}

Related

Why am I getting an error, "ReferenceError: categories is not defined" in AngularJS?

In my understanding, $scope.categories is already defined. Then why am I getting this error and not able to access data from the Json file?
Here is my controller:
(function(){
app.controller('productsCtrl', ['$scope','$cookies', '$http', function($scope,$cookies,$http){
$http.get("controllers/data.json").then(function (response) {
$scope.categories = response.data;
});
$scope.specials = [categories[0].laptops[1], categories[1].accessories[0]];
}]);
})();
Here is my Json file:
[
{
"laptops": [
{
"name": "Asus Laptop",
"price": 300
},
{
"name": "HP Notebook",
"price": 200
}
]
},
{
"accessories": [
{
"name": "WD Hard Drive",
"price": 100
},
{
"name": "WD Blue SSD",
"price": 700
}
]
}
]
You have assigned response data into $scope.categories, you need to use $scope.categories instead of categories and also you should add into $scope.specials once http call completed like
(function(){
app.controller('productsCtrl', ['$scope','$cookies', '$http', function($scope,$cookies,$http){
$scope.specials = [];
$http.get("controllers/data.json").then(function (response) {
$scope.categories = response.data;
$scope.specials.push($scope.categories[0].laptops[1]);
$scope.specials.push($scope.categories[1]. accessories[0]);
});
}]);
})();
There's actually a few issues here. First is you never define a variable named categories, you have a property of the $scope object named that, so you need to access $scope.categories or the response.data setting it directly.
Second, you have a race condition issue. You are trying to access the values of categories outside the promise, meaning potentially before the get request has returned any data. When you use get().then() like you are, the code after the request doesn't wait for the request to finish before it runs, so whatever is faster runs first. Because one of the two operations running is accessing an external endpoint and the other is local javascript code, the flow is almost guaranteed to be this:
send get request to "controllers/data.json"
set $scope.specials - causing your undefined error
set $scope.categories when get request promise resolves
You need to access the categories inside the promise to guarantee that it actually has been defined at the point you are trying to access it:
$http.get("controllers/data.json").then(function (response) {
$scope.categories = response.data;
$scope.specials = [$scope.categories[0].laptops[1], $scope.categories[1].accessories[0]];
});
It's also generally a bad idea to hard code indexes like this, if the data changes you run into a possible index out of bounds error.

Retrieve json data in Angular controller

I'd like to get a couple of values out of a JSON file in my app controller.
I have a JSON file that looks something like this:
{
"login": [
{
"username": "admin",
"password": "admin"
}
],
"header": [
{
"subTitle": "Hello",
"color": "red"
}
]
}
I am attempting to retrieve a value like this:
app.controller('loginCtrl', function($http, $scope) {
data = $http.get('data.json');
console.log(data.login.username);
}
However, all I'm getting in the console is TypeError: Cannot read property 'username' of undefined.
data = $http.get('data.json');
data.then(function(result){
console.log(result.login[0].username);
});
Even though your javascript is synchronous,the call you make is always asynch
$http.get('data.json').then(function (response) {
console.log(response.data)
});
So in your terms javascript called the get function and before it returned with result it executed this console.log(data.login.username);
So you did not got the expected result

Why Angular's $http.get service not working?

I'm having trouble with an example I found on W3Schools about Angular services, on this specific case $http.get one.
I have a json.php file where I have the next JSON:
{
"bands": [
{
"name": "Red hot chilli peppers",
"year": "2009",
},
{
"name": "Maroon 5",
"year": "2005",
},
{
"name": "ACDC",
"year": "2000",
}
]
}
And the Angular and HTML code which should iterate over the object and show the data in it, but it's not working:
JavaScript
var serviceTestApp = angular.module('myapp3', []);
serviceTestApp.controller('controller3', function($scope, $http){
$http.get('json.php').then(function(response){
$scope.myData = response.data.bands;
});
});
HTML
<div ng-app='myapp3' ng-controller='controller3'>
<ul>
<li ng-repeat='x in myData'>
{{x.name}}
</li>
</ul>
</div>
What am I doing wrong here? I use Angular 1.5.0
When you mean not working what exactly do you mean? Do you mean it's successful but doesn't return what you want? In which case you're probably pointing at the wrong thing in the object.
Or does it throw an error?
You should structure it like this:
$http.get('json.php').then(function(response){
// Place a debugger statement here to see if it's successful
$scope.myData = response.data.bands;
}, function(error) {
// No breakpoint needed as you'll see the error in the console window
console.error(error);
});
One other reason could be that you don't have the file in the right place. json.php means that I'd expect it to be in the same folder as the controller.

Is this javascript promise right?

I am learning AngularJS and trying to implement Angular UI Bootstrap Typeahead in a simple search app using Elasticsearch. I want to use the $http service to load asynchronous results and have not worked much with js promises.
UPDATE: I've done some more learning and testing
I've include the Typeahead as a dependency in my app:
var searchApp = angular.module('searchApp', ['elasticsearch', 'ngSanitize', 'ui.bootstrap']);
Here is the js promise code with the ES Match query mapped to the content.autocomplete field:
this.getSuggestions = function(query) {
var deferred = $q.defer();
esClient.search({
index: 'bigtestindex',
body: {
"query": {
"match": {
"content.autocomplete": {
"query": query,
"operator": "and"
}
}
},
"suggest": {
"text": query,
"phraseSuggestion": {
"phrase": {
"field": "content",
"direct_generator": [{
"field": "content",
"suggest_mode": "popular",
"min_word_length": 3,
"prefix_length": 2
}]
}
}
},
"size": 5,
"_source": ["content.autocomplete"]
}
}).then(function(es_return) {
deferred.resolve(es_return);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
};
With this code, I am trying to achieve the asynchronous results as shown here
Here is the relevant html to display possible matches:
<li ng-repeat="gram in autocomplete.edgengrams">
<p ng-mousedown="searchForSuggestion()"><small>Search Suggestions: —</small>{{gram.content}}</p>
</li>
$http.get() return a promise object already , there is no need to wrap the result in another promise object..
For your reference
https://docs.angularjs.org/api/ng/service/$http#get

AngularJS / Restangular routing "Cannot set property 'route' of undefined"

I have a AngularJS-based frontend using restangular to fetch records from a Django backend I've built.
I'm making a call for a client list with the following:
var app;
app = angular.module("myApp", ["restangular"]).config(function(RestangularProvider) {
RestangularProvider.setBaseUrl("http://172.16.91.149:8000/client/v1");
RestangularProvider.setResponseExtractor(function(response, operation) {
return response.objects;
});
return RestangularProvider.setRequestSuffix("/?callback=abc123");
});
angular.module("myApp").controller("MainCtrl", function($scope, Restangular) {
return $scope.client = Restangular.all("client").getList();
});
Chrome is showing the backend returning data with an HTTP 200:
abc123({
"meta": {
"limit": 20,
"next": "/client/v1/client/?callback=abc123&limit=20&offset=20",
"offset": 0,
"previous": null,
"total_count": 2
},
"objects": [{
"id": 1,
"name": "Test",
"resource_uri": "/client/v1/client/1/"
}, {
"id": 2,
"name": "Test 2",
"resource_uri": "/client/v1/client/2/"
}]
})
But once that happens I'm seeing the following stack trace appear in Chrome's console:
TypeError: Cannot set property 'route' of undefined
at restangularizeBase (http://172.16.91.149:9000/components/restangular/src/restangular.js:395:56)
at restangularizeCollection (http://172.16.91.149:9000/components/restangular/src/restangular.js:499:35)
at http://172.16.91.149:9000/components/restangular/src/restangular.js:556:44
at wrappedCallback (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:6846:59)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:6883:26
at Object.Scope.$eval (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:8057:28)
at Object.Scope.$digest (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:7922:25)
at Object.Scope.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:8143:24)
at done (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:9170:20)
at completeRequest (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:9333:7) angular.js:5754
I did a breakpoint on line 395 in in restangular.js:
L394 function restangularizeBase(parent, elem, route) {
L395 elem[config.restangularFields.route] = route;
The first time it hits the breakpoint elem is just an object and route has the value of client.
The second time the breakpoint is hit elem is undefined and route has the value of client.
Any ideas why elem would be undefined the second time around?
When requesting lists, Restangular expects the data from the server to be a simple array. However, if the resulting data is wrapped with result metadata, such as pagination info, it falls apart.
If you are using Django REST Framework, it will return results wrapped like this:
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "Foo"
},
{
"id": 2,
"name": "Bar"
}
]
}
To translate this, you need to create a response extractor function. It's easiest to specify in the module config:
angular.module('myApp', ['myApp.controllers', 'restangular']).
config(function(RestangularProvider) {
RestangularProvider.setBaseUrl("/api");
// This function is used to map the JSON data to something Restangular
// expects
RestangularProvider.setResponseExtractor(function(response, operation, what, url) {
if (operation === "getList") {
// Use results as the return type, and save the result metadata
// in _resultmeta
var newResponse = response.results;
newResponse._resultmeta = {
"count": response.count,
"next": response.next,
"previous": response.previous
};
return newResponse;
}
return response;
});
});
This rearranges the results to be a simple array, with an additional property of _resultmeta, containing the metadata. Restangular will do it's thing with the array, and it's objects, and you can access the _resultmeta property when handling the array as you would expect.
I'm the creator of Restangular.
The restangularizeBase function is called first for your collection and then for each of your elements.
From the StackTrace, the element is OK, but once the collection is sent to restangularizeBase, it's actually undefined. Could you please console.log response.objects? Also, please update to the latest version.
Also, for the default request parameter, you should be using defaultRequestParams instead of the requestSuffix. requestSuffix should only be used for the ending "/"
Let me know if I can help you some more!

Categories

Resources