I am pulling in a JSON file using Angular's $http, but I can't get the formatting right to use ng-repeat for an array of data.
For brevity's sake, here is a sample piece of what I'm working with...
{
name:"Pete",
phone: {
brand: "Nexus",
OS: "Android",
contacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
}
}
Then my ng code is
function($scope, $http) {
$http.get('/my/url')
.success(
function(data){
$scope.contacts = data.phone.contacts;
and my HTML is
<div ng-repeat="names in contacts">
{{names}}
</div>
Only it isn't returning anything. I feel like I am missing a set of [] somewhere?
In JSON:
conAtacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
On view:
<div ng-repeat="names in contacts">
{{names}}
</div>
conAtacts != contacts
Also, you have missed one bracket in JSON.
Should be:
{
name:"Pete",
phone: {
brand: "Nexus",
OS: "Android",
contacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
}
}
Can it be reasons of issue?
Your problem could simply be because you didn't respect the widely recommended practice of the 'point' when you use values that can evolve in AngularJS.
Create an object in the scope :
$scope.dataScope = {}
then in your method
function($scope, $http) {
$http.get('/my/url')
.success(
function(data){
$scope.dataScope.contacts = data.phone.contacts;
and in your html
<div ng-repeat="name in dataScope.contacts">
{{name}}
</div>
Thanks everyone for the as always quick responses. This was a case of sleep deprivation and overthinking things on my part and I left out the ng-controller for the div that the ng-repeat was in.
<div **ng-controller="myCtrl"** ng-repeat="names in contacts">
{{names}}
</div>
Related
When using ng-repeat which approach has better performance? (assuming there are a large number of users)
Approach 1: Filter in Controller
<div ng-repeat="user in users | showBlocked">
<strong>{{user.id}}</strong>
<span>{{user.name}}
</div>
HTML code in template
$scope.users = [
{ id: 1, name: 'alex', isBlocked: true},
{ id: 2, name: 'john', isBlocked: true}
];
JavaScript code in Controller
showBlocked is a filter which returns a list of blocked users
.filter('showBlocked', function() {
return function(users) {
return users.filter(user => user.isBlocked);
}
});
Approach 2: Reassigns users list
<button ng-click="reassignUser(1)">reassign user</button>
<div ng-repeat="user in users">
<strong>{{user.id}}</strong>
<span>{{user.name}}
</div>
HTML code in template
$scope.reassignUser = function (userId) {
if (userId === 1) {
$scope.users = [{id: 1, name: 'alex', isBlocked: true}];
}
// in this case just assigns a single user
};
CodePen Demo: ng-repeat filter vs reassign binding
Do let me know if you need any additional information.
ng-repeat is evaluated on every $digest cycle, making it extremely slow with two-way data-binding due to $dirty checking. The best solution is to use one-way data-binding with {{:: data}} syntax.
But in your example it is indeed better to re-write the array rather than to filter it. The use of filters will work slower, due to each filter creating a sub collection of the original list. However, this can be resolved differently, by hiding the data with ng-show. Here is a post about the complex solution, but you can consider this simple example:
angular.module('myApp', []);
angular.module('myApp').controller('Ctrl', ['$scope', function($scope) {
$scope.users = [{name:"John", "id":0},
{name:"Adam", "id":1},
{name:"Ado", "id":2},
{name:"Chris", "id":3},
{name:"Heather", "id":4},
{name:"Stan", "id":5}];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="Ctrl">
ID: <input ng-model="query" />
<ul>
<li ng-repeat="user in users" ng-show="([user.id] | filter:query).length">
{{user.name}}
</li>
</ul>
</div>
I am developing a simple hybrid mobile app using the Ionic framework. When you search for a last name, a GET request is sent to retrieve all matching last names, and then displays their corresponding ID's. I am having an issue displaying the returned data from the JSON object.
Below is the html page:
<ion-view view-title="Account" ng-controller="AccountCtrl">
<ion-content>
<div class="list">
<div class="item item-input-inset">
<label class="item-input-wrapper">
<input type="text" placeholder="Search" ng-model="name">
</label>
<button class="button button-small" ng-click="searchUser(name)">
Go
</button>
</div>
</div>
<div>
<ul ng-repeat="user in $results">
<li>{{user.id}}</li>
</ul>
</div>
</ion-content>
Next is the js file that successfully returns a populated JSON object with everything I need.
angular.module('starter.controllers', [])
.controller('AccountCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.searchUser = function (name) {
$http.get('https://notrelevantforthis/searchLastName?=' + name).then(function (response) {
console.log(response.data)
//Assign JSON obj to results to repeat through and display data
$scope.results = response.data;
//To show the actual JSON object is returned
//var jsonStr = JSON.stringify($scope.results);
//document.body.innerHTML = jsonStr;
}, function (error) {
console.log(error)
});
};
}]);
Now the important part is the structure of the JSON object itself. I think this is where I am getting confused. The structure is like the following:
{
"response": {
"totalFound": 275,
"start": 0,
"acc": [
{
"id": [
"1"
],
"first_name": [
"Joe"
],
"last_name": [
"Smith"
]
},
{
"id": [
"2"
],
"first_name": [
"John"
],
"last_name": [
"Doe"
]
}]}
}
My problem is iterating through the JSON object using ng-repeat I think. For some reason none of the data is being displayed, but the object is definitely there when looking at the console. Any help or direction in what I am doing wrong would be much appreciated, as I am new to this and have been trying to find the correct way to do this.
EDIT:
Tried using collection-repeat as well offered by the ionic framework but was getting stack limit errors.
When you're assigning response.data to $scope.results, you're literally assigning the HTTP's response body to it, which is the whole JSON object that you have in your question. You would need to actually point to response.data.response.acc if you wanted to ng-repeat through those accounts.
In your template, it should just be ng-repeat="user in results", without the $ in front of results.
Your JSON object lists the id for each account as an array, I'd recommend just giving the literal value without the array, otherwise in your ng-repeat you'll have to use {{user.id[0]}} to actual print the value without printing the array itself.
I've created an example for you here: http://plnkr.co/edit/GYeF4FzVHl8Og5QTFcDx?p=preview
My PHP script returns this JSON data:
{
"userData": {
"userName": "knows_nothing",
"userFullName": "Jon Snow",
"userMoney": "124.01"
}
}
How can I access the variables (userName etc) in my webpage?
eg:
JS
var app = angular.module('dashboard', []);
app.controller('userDataCtrl', function($scope, $http) {
data = "{query:'userData'}"
$.post("api/mysql.php", {query:'userData'})
.then(function (response) {$scope.userData = response.userData;});
});
HTML
<div ng-app="dashboard">
<div ng-controller="userDataCtrl">
<h1> Username: {{ userData.userName }} </h1>
<p> Balance: {{ userData.balance }} </p>
</div>
</div>
This has been driving me insane for hours :(
This is what it outputs when I `console.log(response.userData)
Object { userName: "knows_nothing", userFullName: "Jon Snow", userMoney: "124.01" }
According to $http documentation you should read the response from response.data. So, in your case:
...
.then(function (response) {$scope.userData = response.data.userData;});
should do the trick.
Maybe you have to declare the $scope.userData variable outside of the then-function
check if your response is array, if array then you need to do something like this,
$scope.userData = response[0].userData.
If still not getting solution please share or response format.Entire response structure.
I have been getting an error to make RESTful code for 2 hours.
I have one file has a controller here
angular.module('orderToBeShippedApp',['ng','projectService'])
.controller('orderCtrl',function($scope, Project){
Project.query(function(data){
alert(data);
$scope.projects = data;
});
});
Here is my fatory which is called 'project'.
angular.module('projectService',['ng','ngResource'])
.factory('Project',function($resource){
return $resource('api/url/:projectId.json',{},{
query:{
method:'get',
params: {projectId:"test"},
isArray: false
}
});
});
My html:
<div ng-controller = "orderCtrl" class ="col-sm-8 col-md-9">
<!--Body content -->
<div ng-repeat = "project in projects">
<h2>{{project.name}}</h2>
</div>
</div>
My json is something like
[
{
"age": 0,
"id": "a",
"imageUrl": "a0.jpg",
"name": "b",
"snippet": "Tbaa."
},
{
"age": 1,
"id": "mo",
"imageUrl": "assets/images/phones/mo.0.jpg",
"name": "M\u2122",
"snippet": "The Ned by Android 3.0 (Honeycomb)."
}
]
It doesn't give me any error message on the browser. it seems having a problem on factory function.
Could anyone help me to fix it?
You should change your binding to be name, not ProjectName based on your model definition:
<div ng-controller = "orderCtrl" class ="col-sm-8 col-md-9">
<!--Body content -->
<div ng-repeat = "project in projects">
<h2>{{project.name}}</h2>
</div>
Also, to use ngResource you need to remember to add a script reference to: angular-resource:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular-resource.min.js"></script>
UPDATE:
Remove 'ng' Dependency
Pass the resource to the controller as a dependency.
// resource
angular.module('projectService',['ngResource'])
.factory('Project',function($resource){
return $resource('api/url/:projectId.json',{},{
query:{
method:'get',
params: {projectId:"test"},
isArray: false
}
});
});
// controller
angular.module('orderToBeShippedApp',['projectService'])
.controller('orderCtrl',['$scope','Project', function($scope, Project){
Project.query(function(data){
alert(data);
$scope.projects = data;
});
}]);
Your factory may not be giving a console error however it may not be able to bring back the data. Your factory should be looking like this:
angular.module('projectService',['ng','ngResource'])
.factory('Project',function($resource){
return {
projects: $resource('api/url/:projectId.json', {projectId: '#test'})
}
});
}]);
In your controller it should invoke the method like this:
angular.module('orderToBeShippedApp',['ng','projectService'])
.controller('orderCtrl',['$scope','Project',function($scope, Project){
$scope.projects = Project.projects.get({id: 'test'});
}]);
UPDATE:
In order to relax chrome the xmlHttpRequest error you need to run this command from the chrome.exe folder of your machine:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security
I have a somewhat deep JSON object I am trying to using in an HTML template.
{
"service": {
"name": "example",
"url": "abc.com",
"template": "/abc/def/v1",
"metadata": {
"password": "dontguessme",
"username": "supereasy"
}
}
}
I am including a template with the following HTML code.
<div class="modal-body" ng-include="service.instructionsTemplate"> </div>
In the template there is the following.
<h1>Some example content</h1>
{{service.metadata.password}}
My question is instead of referencing the field password via service.metadata, is there a way I can reference it with just the variable password.
I was trying to dig through some of the Angular docs around scoping and templates but came up empty. I saw you can use ng-init.
I was able to use ng-init="metadata = service.metadata" and was able to reference the field password in the template via metadata.password.
However I would just like to reference it by password.
Any ideas?
You already did ng-init="metadata = service.metadata", why not going a step further and do ng-init="password = service.metadata.password"?
Another way would be to bind $scope.password = service.metadata.password inside the controller thayou're using on that page
Edit: OP asked a more general solution
If you don't know the property names, then your best move would be to bind the metadata object, like you already did, and then iterate through its properties using ng-repeat
in your controller:
$scope.metadata = service.metadata
in your template (view):
<h1>Some example content</h1>
<ul>
<li ng-repeat="element in metadata">{{element}}</li>
</ul>
You can easily set the password to something inside the controller:
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.data = {
"service": {
"name": "example",
"url": "abc.com",
"template": "/abc/def/v1",
"metadata": {
"password": "dontguessme",
"username": "supereasy"
}
}
};
$scope.password = $scope.data.service.metadata.password;
});
Here is a demo: http://plnkr.co/edit/KrKeLIP2ANd0rl5NLywF?p=preview