problems displaying JSON Data with Angular Js ng-repeat - javascript

I am able to retrieve following JSON data (test data) from a php file :
JSON:
[{"id":"1","name":"shabri","desc":"bbkbjkbjbjnnklnln","location":"location","mobile":"498534534","telephone":"4549385","offer":"20","email":"nfnkjrnfnrndnrgnkjr"},{"id":"2","name":"bhagatfergdfgfdg","desc":"vfdgfdbgbbgbg","location":"fbgbgfbgfb","mobile":"544656757","telephone":"4223424","offer":"30","email":"vdsxdvgvgv"},{"id":"3","name":"rddfdgdf","desc":"bdffgd","location":"fghgfhfhgf","mobile":"8598","telephone":"856845","offer":"6","email":"httrdh6kiki"}]
Angular Js Controller
.controller('RestaurantsCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('http://xyz/getRestros.php')
.success(function(data) {
alert(data);
$scope.Restaurants = data;
});
}])
I am sure that JSON data is retrieved because for testing i have alert(data) which displays correct json encoded data in the alert box.
Issue is that data is not getting assigned to $scope.Restaurants. so ng-repeat in html is not populating the list.
ng-repeat populates the list if i hard code $scope.Restaurants.
what's the mistake here ? please help..
EDIT:
hard coded $scope.Restaurants that works:
$scope.Restaurants = [
{ name: 'Shabri', id: 1 },
{ name: 'Bhagat Tarachand', id: 2 },
{ name: 'Udipi', id: 3 },
{ name: 'Shahu', id: 4 },
{ name: 'Bagdadi', id: 5 },
{ name: 'Shiv Sagar', id: 6 }
];
ng-repeat:
<a class="item item-thumbnail-left" ng-repeat="Restaurant in Restaurants | filter: searchText" href="#/app/Restaurants/{{Restaurant.id}}">
<img src="img/default_restro.png" style="margin-top:30px;"/>
<h2 style="font-weight:bold;">{{Restaurant.id}}</h2>
<p>{{Restaurant.name}}</p><br>
<span style="white-space: pre-wrap; font-weight:300;">This is the description about the restaurant click to know more.</span><br>
</a>

You can do debugging in Chrome Developer Tools view (Ctrl-Shift-I) and set breakpoint to see if $scope.Restaurant has value assigned after the line
$scope.Restaurants = data;

You need to parse the returned JSON string into an object.
Try
arrayData = JSON.parse(data);
$scope.Restaurants = arrayData;

It's not actually a answer but i found the root cause of the problem above and might happen with someone.
The free web hosting I was using to host that php file was the culprit.
Everytime that php is executed that web hosting appended some google analytics script at the end after the object ends. That script doesn't appear while live editing that file . i don't know how.
Anyway , i found it when i debugged the $scope.Restaurants again.
It seems that if anything else is echoed with the JSON object thn it would serialize and consider it string.
After correcting and changing the host , difference was spotted and it was considered as actual json objects, and it worked fine.

Related

AngularJS accessing a JSON file within a ng-repeat

Is something like this possible in Angular, I have tried searching but I don't know the exact terms to search for, so first of all, my apologies.
I am using Angular successfully to access a JSON file.
My JSON file contains a list of over 150 events, each event has some basic information like image, title, price, whether the event is sold out etc.
Each event ALSO contains a URL to JSON file about that event.
This file contains much more in depth information about the individual event such as location, difficulty, wheelchair accessible etc.
How can I loop through the first JSON but still extract the information for the "embedded"? JSON file so that I display all information on one page.
I am stuck with being able to understand how to "call" that second JSON file of information while being in a ng-repeat.
and as a beginner to Angular I struggled to search for the correct terminology to help myself.
thanks
EDITED -----
I have created a plunkr here of part of what I am trying to achieve.
http://plnkr.co/edit/zYAhNKdM18pxuK5roPjj?p=preview
<!DOCTYPE html>
<html>
<head>
<style>
#event-list span{display:block;}
#event-list li{clear:both;}
#event-list ul{list-style: none;}
#event-list img{float:left;}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module("exampleApp", []);
app.controller("eventCtrl", function ($scope, $http, $location) {
var eventList = "http://ajax.wiggle.co.uk/api/list/events/?ris=1";
$scope.host = $location.host;
$scope.wiggleEvents = [];
$http({
method: 'JSONP',
url: eventList + '&callback=JSON_CALLBACK'
}).success(function (data, status, headers, config) {
$scope.wiggleEvents = data.Results.Products;
// data contains the response
// status is the HTTP status
// headers is the header getter function
// config is the object that was used to create the HTTP request
}).error(function (data, status, headers, config) {
});
});
</script>
</head>
<body ng-app="exampleApp">
<div ng-controller="eventCtrl">
<div class="row">
<div class="col-md-12" id="event-list">
<ul>
<li ng-repeat="p in wiggleEvents" >
<!-- i need to display a mixture of information from the first JSON file and information from each individual events JSON file -->
<img src="" ng-src="{{p.Image}}?w=125&h=125&a=7" />
<span class='name'>Title: {{p.Title}}</span>
<span>PID: {{p.pid}}</span>
<!--Each of these events has an Apirl which is a JSON file of the information on the event -->
<span>ApiUrl: {{p.ApiUrl}}</span>
<!--AND here i want to add short description of each event. found in the API of each individual event -->
<!--AND here i want to add difficulty rating from API of each individual event -->
<!--AND here i want to add location area of each individual event etc etc etc -->
</li>
</ul>
</div>
</div>
</div>
</body>
</html>
I can successfully get information from the main JSON file, and display the 24 events in the page.
the main JSON file is here:
http://ajax.wiggle.co.uk/api/list/events/?ris=1
each "product" in that JSON has it's own APIUrl to it's own individual JSON file which contains more information about that individual product.
I am trying to output in my html some information from the main JSON and some information from each idividual JSON at the same time.
I am really stuck with how to access each of those individual JSON files, especially as there could be varying amount of "products" contained within the first main file. it happens to be 24 today, but it could be 36 tomorrow etc.
thanks
let's say you have the following json object:
myJsonObj= {
user: {
firstname : "jane",
lastname : "doe"
},
friend: {
firstname: "hancock",
lastname : "john"
}
}
To iterate over properties an object litteral (your json object) using ng-repeat, you must use (key, value) like:
<div ng-repeat="(key,value) in myJsonObj">
<span ng-bind="key"></span> // displays "user" , then "friend"
<span ng-bind="value.firstname"></span> // displays "jane"
<span ng-bind="value.lastname"></span> // displays doe
</div>
read more about iterating over object properties here : ng-repeat .
Edit:
you can also do more stuff by passing some data to a scope function. like
<div ng-repeat="(key,value) in myJsonObj">
// assuming retrieveUrl() is a scope function you wrote
// in order to extract and return the url from the data you passed
// as parameter
<span ng-bind="retrieveUrl(value.url)"></span>
</div>
The best way to fetch json data from a url in the data nested within an ng-repeat would be to write a directive that runs a $http GET. Something like this:
http://plnkr.co/edit/xFCG1p8WwDw9bt6jO49q?p=preview
html
<div ng-repeat="thing in things track by $index">
<get-url-data url="thing"></get-url-data>
</div>
js:
app.directive('getUrlData', function() {
return {
restrict: 'E',
template: '<div>{{vm.jsonData}}</div>',
scope: {
url: '=?'
},
controllerAs: 'vm',
bindToController: true,
controller: function($http) {
vm = this;
$http.get(vm.url).then(function(response) {
vm.jsonData = response;
});
}
};
});
I managed to find an answer for this question.
I followed the chosen answer in this stackoverflow post:
How to bind multiple JSON files in ng-repeat (AngularJS)?
This was written in a way I understood, and it worked for me when I followed it.

Angularjs - Send and Recieve Data Similar to Autocomplete

I am trying to write feature in my application whereby i have an input field, and upon the user typing a value, i should post the value (upon every character typed) to a service/method in my backend code... I should then expect a JSON object of matching results. For example:
If i type: wi
I should see the below returned:
willow
wind
wine
window
william
wilter
wistle
will
If i add an n to the value, e.g I should see the below returned:
window
HTML:
<input type="text" ng-model="serachTerm">
<li ng-repeat="data in SearchResults">
{{ data }}
</li>
JS:
This is a service ive used to get data, but unsure on how to send and listen for updates on every character typed:
app.factory('getDataFactory', function($http) {
return {
getData: function(done) {
$http.get('data.json')
.success(function(data) {
done(data);
})
.error(function(error) {
alert('Something has broke');
});
}
}
});
You should take a look at the directive created by the people over at ui bootstrap.
It is an autocomplete directive that handles the data input and sends it to the backend and renders the suggestions.
They even have working code examples for you to see how to wire the different parts up.
Typeahead

Accessing json data with angular js

I have a couple of questions for accessing model data in my html page using angular. I'm new to angular and have been trying different things but have not been successful so far.
I've set up a contrived example in plunker to illustrate my use case.
My js file looks likes this:
angular.module("myApp", ['ui.bootstrap']);
function AccordionDemoCtrl($scope) {
jsonData = {
"myLocation": "montreal",
"locations" : [
"montreal",
"new york"
],
"carDealers": [
{
"model" : "bmw",
"location": "montreal"
},
{
"model" : "honda",
"location": "new york"
}
]
};
$scope.pageData = {
data: jsonData,
detailContentModel: 'bmw'
}
}
jsonData is the data i obtain from the server. I had trouble putting my formatted HTML code here, so i've linked to my working plunker example below.
I have 2 issues i'm trying to solve:
In my html page i'd like to display car details i.e. model and location in a div based on a user's car selection from an accordion like menu.
The detail div has two elements where
1) i'd like to display the current location of the car and
2) then a dropdown which displays all other locations except for the location associated with the selected car.
e.g.
In my example if a BMW was selected, then the detail div should display the following:
Car Location: montreal
Change location to: [This dropdown should display all locations except montreal]
I'm not entirely sure how to do this. It almost feels like i need to use a xpath type expression to access specific data elements from my model data.
Link to my plunker example.
Note: I'll try to update this question with a few code samples of what i tried - unsuccessfully, once i get a hang of the code formatting here.
Please ignore the formatting of the page. Still new to this stuff..
I think you set up the plnkr quick so I'm assuming you wouldn't really write out all your html for every model and use ng-switch and that was just for speed's sake or else I don't know why you wouldn't hard-code the location too, so when you click on a dealer in my plnkr it sets pageData.selectedDealer and uses it's details (plnkr)
For displaying the location I don't see your problem. Just put the value in braces like you do for the model:
Location: {{pageData.selectedDealer.location}}
To prevent the current location from showing up in your list you could use a filter to remove it:
var app = angular.module("myApp", ['ui.bootstrap']);
app.filter('exclude', function() {
return function(input, excludeValue) {
var result = [];
for (var i = 0; i < input.length; i++) {
if (input[i] != excludeValue) {
result.push(input[i]);
}
}
return result;
}
});
Then use the pipe character | with the filter name, a colon and the arguments to the filter:
<select
ng-options="location for location in pageData.data.locations | exclude:pageData.selectedDealer.location"
ng-model="newLocation" ></select>

can't 'ng-repeat' through javascript array in AngularJS, (by getting a JSON object from Django)

This question is not Django related in any way because my Django view which returns a dummy JSON object works perfectly, just thought I would share the Django view which converts a
Model.objects.all() into pure JSON data then returns this pure data for an Angular controller to read and process through an ng-repeat:
from django.core import serializers
from django.utils import simplejson
def json(request):
all_objects = list(Message.objects.all())
to_json = serializers.serialize('json', all_objects)
return HttpResponse(to_json, mimetype='application/json')
Now on to my question,
I'm not sure if I'm having an Angular issue or pure JavaScript issue. I have an Angular controller called testjson which calls that Django view above which then successfully returns a JSON object like this:
[
{
"pk":1,
"model":"chatfeed.message",
"fields":{
"body":"hey everyone",
"chat_feed":"Dating",
"likes":0,
"author_obj":1,
"parent_channel":1,
"pub_date":"2014-03-18T23:29:27Z"
}
},
{
"pk":2,
"model":"chatfeed.message",
"fields":{
"body":"How's it going?",
"chat_feed":"Dating",
"likes":0,
"author_obj":1,
"parent_channel":1,
"pub_date":"2014-03-18T23:32:05Z"
}
},
{
"pk":3,
"model":"chatfeed.message",
"fields":{
"body":"So what's going on right now",
"chat_feed":"Events",
"likes":0,
"author_obj":1,
"parent_channel":2,
"pub_date":"2014-03-18T23:32:33Z"
}
},
{
"pk":4,
"model":"chatfeed.message",
"fields":{
"body":"Going pretty well actually",
"chat_feed":"Dating",
"likes":0,
"author_obj":1,
"parent_channel":1,
"pub_date":"2014-03-18T23:32:55Z"
}
}
]
And so I would just like to grab the body of a particular chat_feed to be printed in Angular JS using Angular's ng-repeat to get something like this if I wanted all chat messages from chat_feed "Dating":
<div ng-controller="testjson" ng-click="getJSON()">
<ul ng-model="chatfeed">
<li ng-repeat="post in chatfeed">{$ post $}</li>
</ul>
</div>
So in order to get the ng-repeat to work, I believe. I would have to loop through the raw JSON object, grab the 'body' string from each index and store them into an array so that's what I did:
app.controller("testjson", function($scope, $http)
{
$scope.getJSON = function()
{
var JSONObject = $http.get('http://domfa.de/testjson/').success(function(data)
{
$scope.totalfeed = data.length;
chatarray = new Array();
for (var i=0; i < data.length; i++)
{
if (data[i].fields.chat_feed == $scope.currentFeed)
{
chatarray[i] = data[i].fields.chat_feed;
}
}
console.log(chatarray);
$scope.chatfeed = chatarray;
});
}
});
So after all that, my console.log seems to be returning the proper array just fine with the "body"s from the correct chat_feed. Console.log() is doing what I want it to do and the array it prints is properly formatted with perfect syntax, but as for the HTML which calls the ng-repeat="post in chatfeed" angular function it doesn't seem to print anything at all unless I physically copy and past the array console.log() prints out and replace ng-model="chatfeed" with a hardcoded array the console.log() generates for me with no problems using ng-init="['hows it going?', 'hey everyone']".
You are calling getJSON to populate chatfeed when the div is clicked. I wasn't able to trigger getJSON because I couldn't see where to click. So, I added some text to the div:
<div ng-controller="MainCtrl" ng-click="getJSON()">click me!
<ul>
<li ng-repeat="post in chatfeed">{{ post }}</li>
</ul>
</div>
When I clicked the div, I got an error message regarding duplicates in ng-repeat. If currentFeed = 'Dating', then there are 3 matching chat posts with the 'Dating' chat_feed. To allow for the duplicates, I added a tracking expression:
<li ng-repeat="post in chatfeed track by $index">{{ post }}</li>
But then, the list only displayed 'Dating' 3 times. You want the messages to be displayed - not the category. So, I changed the getJSON to add body instead of chat_feed to chatarray:
$scope.chatarray.push($scope.data[i].fields.body)
After making this change, the tracking expression is no long necessary because the body of each chat is unique.
Here is the plunker demo with the final adjustments: http://plnkr.co/edit/J4PtDpeRHO8TVItUnHJw?p=preview

AngularJS POSTs empty requests?

I'm a newbie in AngularJS and I've faced an issue when I try to make a POST request with AngularJS and it POSTs no parameters with it. I use Sinatra as a RESTful interface.
That's how my Sinatra backend looks:
post '/layer/:layer_id' do
#layer = PageLayer.where(id: params[:layer_id]).first
#layer.content = params[:content]
#layer.save
end
If try to POST with Postman chrome extension - it works! Sinatra saves the content properly. So I'm sure that the backend works as it should.
That's how my angular test code looks:
TestCtrl = ($scope, $routeParams, $http, $resource) ->
$scope.layer = []
Layer = $resource('/layer/:id', {id:'#id'})
$scope.layer = Layer.get {id: $routeParams.layerId}, ->
console.log "Got you!"
$scope.saveContent = ->
$scope.layer.$save()
console.log "Saved!"
angular.module('appDirectives', []).directive "test", ->
return (scope, element, attrs) ->
element.bind "blur", ->
console.log("blur!")
scope.saveContent()
And HTML-code:
<div>Content: {{layer.content}}</div>
<div>
<form>
<input type="text" test ng-model="layer.content">
</form>
</div>
So, the only question is: What's wrong? Why I can make correct request with Postman but not with angularJS? Angular returns empty "content" so Sinatra saves it as "" every time.
I've also attached a structure of a layer:
g {id: 27245, page_id: 2302, external_id: 26518, original_upload: null…}
content: "dfgdfg"
external_id: 26518
id: 27245
layerNumber: 8
page_id: 2302
How can I log what exactly angular POSTs?
Hey this is the exact problem I was having, and the answer now seems so obvious. I knew Angular was sending json, but no matter what I tried it wasn't working. This led me in the right direction, but as for parsing json I had to write
ng_params = JSON.parse(request.body.read)
I had to change 'string' to 'read'. Maybe I have a newer version of the json gem or something. My full save process is like this:
post '/api/v1/test' do
ng_params = JSON.parse(request.body.read)
#foo = Foo.new(ng_params)
if #foo.save
puts "Page Saved"
content_type :json
rabl :foos, format: "json"
end
end
I use rabl to format the json to have control over what json data Sinatra sends back (no emails or passwords please)
My Angular code is just this (have not yet implemented put, patch or delete, nor auto update of data just yet. You still have to refresh the page to see the new post.) And to be clear, I have a table named 'foos', where the ActiveRecord model is 'Foo', and one column named 'anything' (other than timestamps and id, which I make sure are always there).
// app declaration
var app = angular.module("App", ['ngResource']);
// data service
app.factory('Foo', ['$resource', function($resource) {
return $resource('/api/v1/test/:id', {id: '#id'});
}]);
// the controller
app.controller('Controller', function($scope, Foo) {
$scope.foos = Foo.query();
$scope.create = function(anything) {
Foo.save({anything: anything}, function(foo){
$scope.foos.push(foo);
});
};
});
Then in my markup the form looks like this, where the important thing is the call to 'create' with 'anything' as the argument in 'ng-submit'. If you have more than one column in your table you call 'create' with more than one argument ex. 'create(anything, bar)'.
<h3>Add something new</h3>
<form ng-submit="create(anything)">
<input ng-model="anything" type="text">
<button type="submit">Do it</button>
</form>
While displaying the data is
<li ng-repeat="foo in foos">
<p>{{foo.anything}}</p>
</li>
This link solved the problem. Just add
gem 'rack-parser'
to your Gemfile and add this code to config.ru. Will work like a charm.
require 'rack/parser'
use Rack::Parser, content_types: {
'application/json' => Proc.new {|body| JSON.parse body }
}
All right, I've solved the issue. Somehow Sinatra was not properly getting POSTs from Angular and was not automatically putting them into params.
So if we parse the request manually - it works. Like that:
post '/layer/:layer_id' do
#updated_layer = JSON.parse(request.body.string)
#layer = PageLayer.where(id: params[:layer_id]).first
#layer.content = #updated_layer['content']
#layer.save
end

Categories

Resources