I would like to know what is wrong with my code when I am creating a simple AngularJS search controller using $.get to retrieve the data from an external json file. It looks like I have all the correct data. JSfiddle is here: http://jsfiddle.net/jmccommas/MLzF7/
controller:
var personApp = angular.module('personApp', []);
personApp.controller('PersonListCtrl', function ($scope, $http) {
$http.get('data/persons.json').success(function(data) {
$scope.persons = data;
});
});
html:
<div ng-controller="PersonListCtrl">
<div class="bar">
Search: <input ng-model="query">
</div>
<ul class="">
<li ng-repeat="person in persons | filter:query">
{{persons.name}}
</li>
</ul>
</div>
json:
[
{
"name": "John Doe"
},
{
"name": "Mike Doe"
},
{
"name": "Sam Doe"
},
{
"name": "Jerry Doe"
},
{
"name": "Paul Doe"
},
{
"name": "Peter Doe"
},
{
"name": "Fred Doe"
},
{
"name": "Ralph Doe"
},
{
"name": "Mike Doe"
},
{
"name": "John Doe"
}
]
There are three small things which is going wrong (at least in the JS Fiddle)
1. You have set the JS to load on DOM Ready. Change that to no-wrap in head.
2. In the ng-repeat, you have persons.name. It should be person.name. You are getting person when you are lopping through persons.
3. The JSON in the fiddle is not present. So in my own fiddle, I have for now hard coded the object
http://jsfiddle.net/amitavroy/rCrGP/
Change your li to the following
<li ng-repeat="person in persons | filter:query">{{person.name}}</li>
Related
I am trying to read the json data from a static json file that I have for testing on a local web server but I cannot get anything to show up with using the $http.get() service. I looked at a few other similar questions here but all accepted answers account for use of the promise methods, however on the angularjs v1.6.x+ these have been depreciated.
Initially I tried setting my json data on a variable inside of the controller, and everything worked fine, however once I moved to a JSON file nothing shows up. My first error was that I was unaware the JSON file has to be in ANSI format for the JSON.parse() angular calls to be able to work. Before switching the file encoding to ANSI I was getting syntax errors and my json structure was correct. (some text editor like Dreamweaver will create JSON files in UTF-8 format).
At this point when I inspect the webpage there are no JS errors on the console whatsoever, however no data shows up at all. Here is what I have:
My events.json
[
{
"day" : "Monday",
"objective" : "Pipeline",
"sessions" : [
{
"title" : "Leadership Excellence Luncheon",
"start" : "11:30am",
"end" : "1:00pm",
"location": "room A"
},
{
"title" : "Veteran Resume Workshop",
"start" : "1:15pm",
"end" : "2:00pm",
"location": "room B",
"speakers" : [
{
"name": "John Doe",
"title": "Analyst",
"company": "Appel",
"headshot" : "http://placehold.it/119x134.jpg",
"bio": "john-doe/",
},
{
"name": "Jane Doe",
"title" : "VP",
"company": "Lancer",
"headshot" : "http://placehold.it/119x134.jpg",
}
]
}
]
},
{
"day" : "Tuesday",
"objective" : "Pipeline",
"sessions" : [
{
"title" : "Leadership Excellence Luncheon",
"start" : "11:30am",
"end" : "1:00pm",
"location": "room A"
},
{
"title" : "Veteran Resume Workshop",
"start" : "1:15pm",
"end" : "2:00pm",
"location": "room B",
"speakers" : [
{
"name": "John Doe",
"title": "Analyst",
"company": "Appel",
"headshot" : "http://placehold.it/119x134.jpg",
"bio": "john-doe/",
},
{
"name": "Jane Doe",
"title" : "VP",
"company": "Lancer",
"headshot" : "http://placehold.it/119x134.jpg",
}
]
}
]
}
}
Here is my app.js
(function() {
var app = angular.module('Agendas',[]);
app.controller('TableController', ['$scope', '$http',
function($scope,$http) {
$scope.title = "test";
$scope.events = [];
$http({
method: 'POST',
url: 'http://localhost/ang/data/events.json',
}).then( function(response) {
$scope.events = response;
});
}]);
})();
Here is my index.html
<!doctype html>
<html>
<head>
.....
</head>
<body>
....
<div id="agenda" class="mainCont container-fluid well" ng-app="Agendas" ng-controller="TableController">
<div id="day" ng-repeat="event in events">
<h1>{{ event.day }} — {{ event.objective }}</h1>
<div id="sess" ng-repeat="session in event.sessions">
<div style="width: 140px; float: left; clear: left;">{{ session.start }} - {{ session.end }}<br><br><em>Location: {{ session.location }}</em></div> <div style="float: left;"><em>{{ session.title }}</em> <br>
<div class="panelist" ng-repeat="speaker in session.speakers"><img ng-src="{{ speaker.headshot }}"><br>
<a ng-href="{{ speaker.bio }}">{{ speaker.name }}</a><br>
{{ speaker.title }} <br>
{{ speaker.company }}</div>
</div>
</div>
<div class="aghr"></div>
</div>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
I noticed that your JSON file contains some errors. It could be related.
The ending tag should be one to close the array. ]instead of }.
The last field of a JSON object should not have a comma. E.g.:
{
"name": "John Doe",
"title": "Analyst",
"company": "Appel",
"headshot" : "http://placehold.it/119x134.jpg",
"bio": "john-doe/", <--- remove comma
}
You can use a website as jsonlint to validate your JSON.
** As suggested, you might have to clear the browser cache first.
** Additionally change
$scope.events = response;
to
$scope.events = response.data;
Finally trying to learn AngularJS and I can't quite figure out how to make components work recursively. I have a simple example that's not rendering as expected.
HTML
<body ng-app="myApp" ng-controller="myCtrl as vm">
<nested-list list="vm.list"></nested-list>
</body>
JavaScript
angular.module('myApp', [])
.controller('myCtrl', ['$scope', function($scope) {
$scope.list = [
{ "name": "Item 1" },
{ "name": "Item 2",
"subItems": [
{ "name": " Item 2.1" }
]
},
{ "name": "Item 3",
"subItems": [
{ "name": " Item 3.1" },
{ "name": "Item 3.2",
"subItems": [
{ "name": "Item 3.2.1" },
{ "name": "Item 3.2.2" }
]
}
]
}];
}])
.component('nestedList', {
bindings: {
list: '<'
},
template: `
<div ng-repeat="item in $ctrl.list" >
<div> {{item.name}} </div>
<nested-list list="item.subItems"></nested-list>
</div>
`
});
Undoubtedly because I'm missing something obvious, the list from the app's main controller myCtrl isn't getting bound to the root component. If anyone can provide insight, I'd be grateful.
Stephen
As you are using controllerAs, you should be binding values to controller this(context) instead of binding values to $scope.
.controller('myCtrl', [function() {
var vm = this;
vm.list = [ ..];
}]);
Plunker Here
I have a custom directive that is holding an array of JavaScript objects.
The object is a little complex and lengthy but I will display something similar to point out my problem:
A JSON.stringify of this displays the following:
[
{
"Id": 1,
"Name": "John Doe",
"EMail": "john#doe.com"
},
{
"Id": 2,
"Name": "Jim Doe",
"EMail": "jim#doe.com"
},
{
"Id": 3,
"Name": "Jeff Doe",
"EMail": "jeff#doe.com"
}
]
I am further using ng-repeat to display the values in a tabular form on my HTML.
The values are coming from an API call that fetches them from a database.
I want to swap - say the entire Object with Id 1 with the entire Object with Id 3 so that during my tabular display I can see Id 3 object details first and Id 1 object details last, without breaking any functionality.
What would be the best possible solution to do this within the frontend itself?
How about just swapping them using a temp variable?
var arr = [{"Id":1,"Name":"John Doe","EMail":"john#doe.com"},
{"Id":2,"Name":"Jim Doe","EMail":"jim#doe.com"},
{"Id":3,"Name":"Jeff Doe","EMail":"jeff#doe.com"}]
var tmpObj = arr[0];
arr[0] = arr[2];
arr[2] = tmpObj;
If you want to reverse the array, use Array.prototype.reverse()
var app = angular.module("myApp", []);
app.controller("myController", function($scope) {
var arr = [
{
"Id": 1,
"Name": "John Doe",
"EMail": "john#doe.com"
},
{
"Id": 2,
"Name": "Jim Doe",
"EMail": "jim#doe.com"
},
{
"Id": 3,
"Name": "Jeff Doe",
"EMail": "jeff#doe.com"
}
];
$scope.array = arr.reverse();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myController">
<div ng-repeat="item in array">
{{item.Id}} - {{item.Name}} - {{item.EMail}}
</div>
</div>
</div>
Very simple user to user messaging piece that I'm struggling with the interface in an app to use ng-repeat on the items.
Here is the data:
{
"ID": 4118,
"CreatedDate": "2015-08-20T03:12:50.397",
"recipient": [
{
"ID": 13,
"FirstName": "Heather",
"LastName": "Martin",
"ProfileImage": "https://../profilepictures/13"
}
],
"sender": [
{
"ID": 1046,
"FirstName": "Brad",
"LastName": "Martin",
"ProfileImage": "https://../profilepictures/1046"
}
],
"messages": [
{
"ID": 4137,
"ConversationID": 4118,
"UserID": 1046,
"Body": "hey",
"CreatedDate": "2015-08-20T14:34:42.4716233+00:00"
}
]
}
In the controller I get the conversations out of LS, one conversation is one record in LocalStorage, the JSON above will represent one conversation.
$scope.convo = JSON.parse(localStorage.getItem("convo-" + $stateParams.chatId));
Here is the structure I am trying to achieve (again, very simple, nothing fancy).
<ul>
<li class="item-avatar-left" ng-repeat="c in convo track by $index">
<img ng-src="{{c.recipient[0].ProfileImage}}" />
<p class="bubble speech">
{{c.messages[0].Body}}
</p>
</li>
</ul>
I've tried multiple variations on the ng-repeat directive.
Essentially what I'd like to achieve is just showing one <li> per each message.
Current result:
Console output of a conversation from LS:
You can try normally by ng-repeat
In controller like:
$scope.convo = [
{
"ID": 4118,
"CreatedDate": '2015-08-20T03:12:50.397',
//...... as your info
}
];
In HTML:
<ul>
<li class="item-avatar-left" ng-repeat="c in convo">
<img ng-src="{{c.recipient[0].ProfileImage}}" />
<p class="bubble speech" ng-repeat="m in c.messages">
{{m.Body}}
</p>
</li>
</ul>
NB: your $scope.convo need to be an array
I am trying to bind data from a web service and then use that data to pre-populate a form. All form controls are binding correctly except for a single multi-select element. If I manually select an option the model does update. Below is my controller:
myApp.controller('AdminVideosEditCtrl', [
'$scope',
'$http',
'$routeParams',
'$location',
function($scope, $http, $routeParams, $location) {
$http.get('/videos/' + $routeParams.videoId + '?embed=presenters').success(function(data) {
$scope.video = data.data
// Load providers
$http.get('/providers').success(function(data) {
$scope.providers = data.data;
// Load Presenters
$http.get('/presenters').success(function(data) {
$scope.presenters = data.data;
});
});
});
}
]);
Once the final request returns, my model looks like this (output via {{ video | json }}):
{
"id": "ca3ca05a-834e-47b1-aaa1-3dbe38338ca9",
"title": "Doloremque iure consequatur quam ea.",
"is_public": false,
"is_visible": true,
"url": "http://someurl.com/",
"provider_id": "1b4d18eb-d56c-41ae-9431-4c058a32d651",
"level_id": "38ed7286-da05-44b9-bfb9-e1278088d229",
"duration": "17:38",
"transcript_file": "rerum-sint-voluptatum.md",
"presenters": [
{
"id": "5111531d-5f2a-45f5-a0c4-4fa3027ff249",
"first_name": "First",
"last_name": "Last",
"full_name": "First Last"
}
],
"provider": {
"id": "1b4d18eb-d56c-41ae-9431-4c058a32d651",
"title": "You Tube"
}
}
Here is how the multi-select looks in my view:
<div class="form-group">
<label for="presenters" class="col-lg-2 control-label">Presenters</label>
<div class="col-lg-10">
<select multiple="multiple" class="form-control" id="presenters" ng-model="video.presenters" ng-options="presenter.full_name for ( id , presenter ) in presenters">
</select>
</div>
</div>
The select element populates correctly, and I would expect for it to default with the "First Last" element selected, however nothing is selected. I know my model is initialized correctly because if I manually select the element nothing in the model changes (if I select a different element it does, but still retains the same structure as it does on initial page load).
I tried adding a $scope.$apply call, and I also tried $scope.$root.$eval(), neither of which worked.
Update
The presenters model (containing all of the presenters) looks like this after it is fetched from the service (names have been changed to protect the innocent):
[
{
"id": "47b6e945-2d4b-44c2-b44b-adb96460864d",
"first_name": "First",
"last_name": "Last",
"full_name": "First Last"
},
{
"id": "5111531d-5f2a-45f5-a0c4-4fa3027ff249",
"first_name": "One",
"last_name": "Two",
"full_name": "One Two"
},
{
"id": "7cb1e44b-2806-4576-80b2-ae730ad356f7",
"first_name": "Three",
"last_name": "Four",
"full_name": "Three Four"
}
]
Solution
Just put this at the bottom of your controller
$scope.video.presenters.forEach(function(obj, idx){
$scope.presenters.forEach(function(presenter, jdx){
if (obj.id === presenter.id) {
$scope.video.presenters = [$scope.presenters[jdx]]
}
});
});
JSFIDDLE
More Robust Solution
This is more robust as you might want to preselect multiple options. This solution pushes each selected option into an array and then assigns it to $scope.video.presenters model
var selectedOptions = [];
$scope.video.presenters.forEach(function (obj, idx) {
$scope.presenters.forEach(function (presenter, idj) {
if (obj.id === presenter.id) {
selectedOptions.push($scope.presenters[idj]);
$scope.video.presenters = selectedOptions;
}
});
JSFIDDLE
Note: Ideally you should be using the id key as the unique for the objects.
This solution assumes and only caters for preselecting one option.