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.
Related
I am using Angular 1 and the angular-file-upload plugin.
I want to create an array populated in the following way:
result = [{
name: "whatever string",
uploadedFilePath: "/whatever/path/image.png"
}, {
name: "other string",
uploadedFilePath: "/whatever/path/otherImage.png"
}]
In the view I have an ng-repeat with a name input and a file-input field and a button that creates another card with the same fields in the ng-repeat.
I can add the names to the array in the corresponding objects without much issue.
If there is a single upload input and not in the ng-repeat (either file input or multiple) I can easily get the path by taking it through the event:
vm.uploader.onCompleteItem = function(fileItem, response, status, headers) {
vm.uploadedFilePaths.push(response.filePath);
};
and then getting the paths from vm.uploadedFilePaths.
I don't know any good practices for showing the file input in the view so I'm using:
<input type="file" ng-file-model="files" multiple />
<p ng-repeat="file in files">
{{file.name}}
</p>
I don't know how to get the paths corresponding to each of the uploaded files and adding them to the corresponding object in the array.
I'm somewhat confident I should be using the event vm.uploader.uploadAll(); at the end to put them in the corresponding place ? But how do I find out the corresponding place for each, I'm not sure how I can utilize $index here.
I'm very new to using angular-file-upload so I'd appreciate it very much if you could explain it like it's for a newbie.
Declare a object as
vm.fileDetails = {
name:"",
path:""
}
and then on the completion of upload
vm.uploader.onCompleteItem = function(fileItem, response, status, headers) {
vm.fileDetails.name = response.fileName;
vm.fileDetails.path = response.filePath;
vm.uploadedFilePaths.push(vm.fileDetails);
};
Now you can use this array in your view to get details.
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.
I'm trying to implement a very basic system involving angular.js and JSON, but I can't get it to behave. All I want to do is get the value for a particular field in my JSON file and spit it onto the page. Can anyone see why this isn't working? It finds the database every time, but I can't seem to access the object.
HTML & JS
<html lang="en" ng-app="ngApp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.min.js"></script>
<script>
var ngApp = angular.module('ngApp', []);
ngApp.controller('ngCtrl', function($scope, $http){
$http.get("db.json").success(function(data){
console.log("Database found");
$scope.data = data;
});
});
</script>
<body ng-controller="ngCtrl">
<div>Data goes here: {{data.field1}}</div>
</body>
</html>
JSON
[
{
"field1":"data1",
"field2":"data2"
}
]
I'm very new to angular, so I wouldn't be surprised if there's something I missed.
Your json response is array of objects. So, you've to use array notation to access the data from it.
See the highlighted changes below:
<div>Data goes here: {{data[0].field1}}</div>
// ^^^
You might want to use ng-repeat to loop over all the data
<body ng-controller="ngCtrl">
<div ng-repeat="item in data">
<span> Field1 : {{item.field1}}</span>
<span> Field2 : {{item.field2}}</span>
</div>
</body>
From first look it seems that json data returned is array of an objects. Try this
data[0].field1
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
Ok, first a simplified portion of the Javascript:
//the network values below are later dynamically
//reloaded at runtime from a remote API
$scope.networks = [{id: 5, name: "Network 1"}];
$scope.campaign = {
paths: [
{offers: [
{name: "Site1",
network: $scope.networks[0],
uri: "http://uri1.com"},
{name: "Site2",
network: $scope.networks[0],
uri: "http://uri2.com"}]}]};
And the relevant part of the HTML:
<div ng-repeat "path in campaign.paths">
<div ng-repeat="offer in path.offers">
<input type="text" ng-model="offer.name" />
<input type="text" ng-model="offer.uri" />
<select ng-model="offer.network"
ng-options="n.id as n.name for n in networks">
</select>
</div>
</div>
The problem is that this always gives me a blank option as the first option whenever I try to set the model for the to offer.network. I have read
Why does AngularJS include an empty option in select?
and
AngularJS - extra blank option added using ng-repeat in select tag, but they only seem to apply to selects that are at the top level (i.e., not using a model inside an ng-repeat). My problem is that I need to update a model that is part of a nested ng-repeat.
EDIT: I should have also included the below code; this is what is actually breaking everything. This code runs after the original array is set up:
$scope.getNetworks = function () {
$http.get('/api/networks/nameid'
).success(function (data, status, headers, config) {
$scope.networks = data;
});
};
$scope.getNetworks();
The above backend call returns an array of objects of the form {id: id, :name "name"}.
And yes, I could populate the select statically from the server side, but I would really like to know how to make this work in the general case.
Since you use the n.id in the comprehension expression of the drop down list, you should pre-populate the offer.network with the id value like this
network: $scope.networks[0].id
And since the data is populated dynamically, you can do something like this. (For the demo purpose, I just use a very dumb way to populate the values. But you get the idea.)
$scope.getNetworks().then(function(data){
$scope.networks = data;
//populate the default value
$scope.campaign.paths[0].offers[0].network = $scope.networks[0].id;
$scope.campaign.paths[0].offers[1].network = $scope.networks[0].id;
})
Working Demo