I'm having trouble accessing the nested JSON using the ng-repeat directives. I know it is working because the not nested part of the JSON object is displaying.
Here is a plunker of my code: http://plnkr.co/edit/V2iURMa8t7vG9AqDFMOf?p=preview
JavaScript:
var app = angular.module("app", [ ]);
app.controller("AppTest", function($scope){
$scope.currentInfo=[{"id":0,"article":"JavaScript Conquers the World","publisher":"Daily Times","meta_data":{"comments":4}},
{"id":1,"article":"The Problem with Foobar","publisher":"New York Times","meta_data":{"comments":27}}];
$scope.tableInfo=[{"name":"id","dataType":"Integer","isEditable":false},
{"name":"article","dataType":"String","isEditable":true},
{"name":"publisher","dataType":"String","isEditable":false},
{"name":"meta_data.comments","dataType":"Integer","isEditable":false}];
});
HTML:
<body ng-app="app" ng-controller="AppTest as app"
<table>
<tbody ng-repeat="anotherItem in currentInfo">
<tr>
<td ng-repeat="item in tableInfo">{{anotherItem[item.name]}}</td>
</tr>
</tbody>
</table>
</body>
Another solution that is better is to add function in the controller that will resolve the value for you. The issue with your solution is that you need Angular to resolve meta_data.comments, but it is treating it as the string that is used in the array lookup since it has already resolved item.name.
$scope.resolveLookup = function(object, lookup) {
var depth = lookup.split('.').length;
var currentObj = object;
for(var x=0; x<depth; x++) {
currentObj = currentObj[lookup.split('.')[x]];
}
return currentObj;
};
Then change the HTML to look like:
<td ng-repeat="item in tableInfo">{{resolveLookup(anotherItem,item.name)}}</td>
Here is the Plunker: http://plnkr.co/edit/RVd2ncwstyQtCtdhcC9U?p=preview
The issue is that it is putting 'metadata.comments' in the [] and it doesn't realize that it needs to be resolved again by angular. I can't think of fix without changing the data structure of your 'tableInfo' object.
Here is how I would do it.
Change table info to:
$scope.tableInfo = [{
"name": ["id"],
"dataType": "Integer",
"isEditable": false
}, {
"name": ["article"],
"dataType": "String",
"isEditable": true
}, {
"name": ["publisher"],
"dataType": "String",
"isEditable": false
}, {
"name": ["meta_data", "comments"],
"dataType": "Integer",
"isEditable": false
}];
Change your HTML to:
<td ng-repeat="item in tableInfo" ng-if="item.name.length==1">{{anotherItem[item.name[0]]}}</td>
<td ng-repeat="item in tableInfo" ng-if="item.name.length==2">{{anotherItem[item.name[0]][item.name[1]]}}</td>
Here is the Plunker: http://plnkr.co/edit/q9lHZ2TD7WZ74b2f6Ais?p=preview
Related
I have a nested json object array and I am able to display Inner Items grouped By Info in HTML using ng-repeat. I have a checkbox in front of each Inner Item where I am handling ng-click event and passing the selected Inner Items to the controller. But now I also wanted to pass Info id in the ng-click event. Can I concatenate the Info array to Inner items array in the ng-click
Here is the json :
[
{
"Info": {
"id": "a1",
"name": "a1-Info",
"InnerInfo": [
{
"name": "xyz"
}
]
},
"InnerItems": [
{ "id": "i1" },
{ "id": "i2" }
]
}
]
<tr ng-repeat=“I in MyData">
<td> {{I.Info.name}}
<table>
<tr><td>
<div ng-repeat=“item in I.InnerItems ">
<input type="checkbox" name="values" ng-click=“getInfo(I);getInnerItems(item)” ng-true-value="1" ng-false-value="0"/>{{item.name}}
</div>
</td>
</tr>
</table>
</td>
</tr>
I need to pass both arrays to one function instead of the above way. Any suggestions?
Use an expression with ng-click to set a property on the controller.
Say you have a property on the controller activeData, then use ng-click like this:
ng-click="activeData = [I , item]"
I have passed multiple parameters to one of my functions itself like getInfo (I, items) and tried to access in controller without having to use any property. It works fine
Hello here's my json :
[
{
"name": "AAAAAA",
"loading": "False",
},
{
"name": "BBBBBB",
"loading": "45%",
},
{
"name": "CCCCCC",
"loading": "12%",
},
{
"name": "DDDDDD",
"loading": "False",
}
]
My javascript :
var app = angular.module('app', []);
app.service('service', function($http, $q){
var deferred = $q.defer();
$http.get('names.json').then(function(data){
deferred.resolve(data);
});
this.getNames = function() {
return deferred.promise;
}
});
app.controller('FirstCtrl', function($scope, service, $http) {
var promise = service.getNames();
promise.then(function (data) {
$scope.names = data.data;
console.log($scope.names);
}
);
HTML :
<tbody>
<tr ng-repeat="name in names">
<td>{{name.name}}</td>
<td>{{name.loading}}</td>
</tr>
</tbody>
What i try to do is loading bar for name.loading %. I get it from server, and the % is loading for something, so it still load (ex. in first second 15%, in second 25%...), and when its 100% name.loading = "False". I need loading bar in the table name.loading, only when its %, when its "False", in table should be just "False".
Thanks in advance
You can use progress in html5.
Edit your code like below.
<td><progress value="{{name.loading}}" max="100" ng-if="name.loading != 'False'">{{name.loading}} %</progress></td>
You can use ngIf directive to achieve that.
<tbody>
<tr ng-repeat="name in names">
<td>{{name.name}}</td>
<td ng-if="name.loading !== 'False'">{{name.loading}}</td>
</tr>
</tbody>
I've seen so many ways to do this, but most are pretty old and I want to make sure I'm doing this correctly. Right now, the way I'm using isn't working and I feel like I'm missing something.
I'm getting the JSON back fine, I just need to get it to display in a table after I click the button.
Here is the JSON. This is how I'm going to get it from our server, I can't add any "var JSON =" or add any scope like "$scope.carrier" to the data, unless there's a way to add it after I've fetched the data.
{
"carrier":
[
{
"entity": "carrier",
"id": 1,
"parentEntity": "ORMS",
"value": "Medica"
}, {
"entity": "carrier",
"id": 2,
"parentEntity": "ORMS",
"value": "UHG"
}, {
"entity": "carrier",
"id": 3,
"parentEntity": "ORMS",
"value": "Optum"
}, {
"entity": "carrier",
"id": 4,
"parentEntity": "ORMS",
"value": "Insight"
}, {
"entity": "carrier",
"id": 5,
"parentEntity": "ORMS",
"value": "Insight"
}
]
}
Here is the app.js file to bring back the JSON data:
var app = angular.module('myTestApp', []);
app.controller('myController', ['$scope', '$http', function($scope, $http) {
var url = 'test.json';
$scope.clickButton = function() {
$http.get(url).success(function(data) {
console.log(data);
});
}
}]);
And then of course the HTML:
<div class="col-lg-12 text-center">
<button type=button class="btn btn-primary load" ng-click="clickButton()">Click!</button>
<table class="">
<tbody ng-repeat="carrier in carriers">
<tr>
<td>
<h3 class="">{{ module.entity }}</h3>
<h3 class="">{{ module.id }}</h3>
<h3 class="">{{ module.parentEntity }}</h3>
<h3 class="">{{ module.value }}</h3>
</td>
</tr>
</tbody>
</table>
</div>
I'm also wondering if I can use the ng-grid to put this in a table. I know they just upgraded it to ui grid so I'm not sure if this is still a feasible approach.
Also, I'm not getting errors, the data just won't display in the table right now. All I know is its returning the data properly, just not displaying in the table.
Any help is appreciated.
I looked at your plunker seems like you need to:
add angular script
wire the app and the controller
your variable in the repeater is wrong, I change it
take a look to this fixed plunker:
http://plnkr.co/edit/TAjnUCMOBxQTC6lNJL8j?p=preview
$scope.clickButton = function() {
$http.get(url).success(function(returnValue) {
alert(JSON.stringify(returnValue.carrier));
$scope.carriers = returnValue.carrier;
});
}
You never assign the value of the returned array to $scope.carriers.
At the line where you say console.log(data); add this:
$scope.carriers = data.data;
Here is the updated clickButton function (with a variable name change to reduce confusion):
$scope.clickButton = function() {
$http.get(url).success(function(returnValue) {
$scope.carriers = returnValue.data;
});
};
I have an api endpoint at /api/pin that returns the following JSON:
{
"num_results": 4,
"objects": [
{
"id": 1,
"image": "http://placekitten.com/200/200/?image=9",
"title": "Test"
},
{
"id": 2,
"image": "http://placekitten.com/200/200/?image=9",
"title": "test"
},
{
"id": 3,
"image": "www.test.com",
"title": "test"
}
],
"page": 1,
"total_pages": 1
}
I want to map this into a knockout observable array and display it in my page. Here's my js file:
define(['knockout', 'text!./pins.html'], function(ko, templateMarkup) {
function Pins(params) {
var self = this;
self.agents = ko.observableArray([]);
$.getJSON('/api/pin', function(data){
self.agents = ko.mapping.fromJS(data);
});
}
return { viewModel: Pins, template: templateMarkup };
});
My html:
<b data-bind="agents.num_results"> results </b>
<table>
<tbody data-bind="foreach: agents.objects">
<tr>
<td data-bind="text: image"></td>
<td data-bind="text: title"></td>
</tr>
</tbody>
</table>
I get nothing rendered, other than the word "results".
I know that I can create a view model that represents the JSON data and push it into the array during the getJSON (and I've done that successfully). But I thought the whole point of the knockout mappings library was so that you didn't have to do that. I guess I'm having trouble wrapping my head around what exactly I'm doing wrong here. Seems like I must be missing something super obvious, but I'm pulling my hair out trying to figure out what's wrong.
So I figured it out. Basically I had to mock up a PinViewModel like this:
define(['knockout', 'text!./pins.html'], function(ko, templateMarkup) {
function PinVewModel (){
this.objects = ko.observableArray();
}
function Pins(params) {
var self = this;
self.agents = new PinVewModel();
$.getJSON('/api/pin', function(data){
ko.mapping.fromJS(data, {}, self.agents);
});
}
return { viewModel: Pins, template: templateMarkup };
});
And if anyone is interested in the POST part...
function Pin(data){
this.image = ko.observable(data.image);
this.title = ko.observable(data.title);
}
this.createPins = function(formElement){
formPin = new Pin({image: formElement.pin_url.value, title: formElement.pin_name.value});
$.ajax("/api/pin", {
data: ko.toJSON(formPin),
type: "post", contentType: "application/json",
success: function(result) {
self.pins.objects.push(formPin);
}
});
};
There's probably redundancy I'm doing in here, but it works and achieves the desired results.
I know this is a bit basic but i'm struggling to get my head round it, I have a web service that returns the follow JSON:
[{"search_id":"1","user_id":"1","all_words":"php","not_words":"C++","one_words":"java","created_at":null,"updated_at":null,"search_name":null},{"search_id":"2","user_id":"1","all_words":"second","not_words":"not","one_words":"one","created_at":null,"updated_at":null,"search_name":null}]
So when it gets to angular I end up with the following:
Array[2]
0: Object
$$hashKey: "object:5"
all_words: "php"
created_at: null
not_words: "C++"
one_words: "java"
search_id: "1"
search_name: null
updated_at: null
user_id: "1"
__proto__:
1: Object
$$hashKey: "object:6"
all_words: "second"
created_at: null
not_words: "not"
one_words: "one"
search_id: "2"
search_name: null
updated_at: null
user_id: "1"
__proto__:
Which is a real pain to work with in ng-repeat, how would I go about being able to access it like so(rough example)
ng-repeat="item in items"
{{ item.search_id }}
to be clear the only way I can get data from it is by doing:
<tr ng-repeat="items in data">
<td ng-repeat="(key, value) in items"> </td>
</tr>
Controller code is here:
testAPI.getSearches().then(function (data) {
$scope.data= testAPI.searchList();
console.log($scope.data);
}, function (error) {
alert("Error in getSearches");
});
getsearches as follows, searchList returns the searches variable:
getSearches: function() {
var deferred = $q.defer();
$http({
url: 'http://localhost/api/api/tray/search/list'
}).success(function (data) {
searches = data;
console.log(data);
deferred.resolve(data);
}).error(function (data) {
alert('Error');
deferred.reject(data);
});
return deferred.promise;
},
Hrm thanks for the responses guys but the plain "item in data" does not work in my case I have to use (key,value) in items inside a nested ng repeat, any ideas what i'm missing?
By the way not sure if this matters put the HTML is inside a partial and i'm using ui router for the navigation?
UPDATE
Thank you all very much for your help, looks like this problem was caused by a typo on a containing HTML element and the controller not being setup properly because I messed up the ui router setup. Once i've had a chance to make sure i've missed nothing else i'll post back.
This seems to be working fine. Just make sure you're data is tied to your $scope.
http://jsfiddle.net/f4zdfh72/
function MyCtrl($scope) {
$scope.data = [{
"search_id": "1",
"user_id": "1",
"all_words": "php",
"not_words": "C++",
"one_words": "java",
"created_at": null,
"updated_at": null,
"search_name": null
}, {
"search_id": "2",
"user_id": "1",
"all_words": "second",
"not_words": "not",
"one_words": "one",
"created_at": null,
"updated_at": null,
"search_name": null
}]
}
<div ng-controller="MyCtrl">
<div ng-repeat='item in data'>
THIS IS DATA: {{item.one_words}}
</div>
</div>
Note: run it in the JSFiddle. Stack snippet is just for code preview
works fine for me: http://plnkr.co/edit/ubiWcF3CemeKo6dzkvNC?p=preview
var app = angular.module("myApp", []);
app.controller('myCtrl', ['$scope', function($scope){
$scope.data = JSON.parse('[{"search_id":"1","user_id":"1","all_words":"php","not_words":"C++","one_words":"java","created_at":null,"updated_at":null,"search_name":null},{"search_id":"2","user_id":"1","all_words":"second","not_words":"not","one_words":"one","created_at":null,"updated_at":null,"search_name":null}]')
}]);
Maybe I am missunderstanding, but this should actually work. Plunker The Example includes the Controller As and $scope approaches.
Controller
angular
.module("app", [])
.controller("MainController", ['$scope', function($scope) {
var vm = this;
var json = '[{"search_id":"1","user_id":"1","all_words":"php","not_words":"C++","one_words":"java","created_at":null,"updated_at":null,"search_name":null},{"search_id":"2","user_id":"1","all_words":"second","not_words":"not","one_words":"one","created_at":null,"updated_at":null,"search_name":null}]';
vm.items = JSON.parse(json);
$scope.items = JSON.parse(json);
}]);
html
<!DOCTYPE html>
<html ng-app="app">
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body ng-controller="MainController as vm">
<h1>Items Controller As</h1>
<div ng-repeat="item in vm.items">
{{ item.search_id }}
</div>
<h1>Items $scope</h1>
<div ng-repeat="item in items">
{{ item.search_id }}
</div>
<script data-require="angular.js#1.3.6" data-semver="1.3.6" src="https://code.angularjs.org/1.3.6/angular.js"></script>
<script src="script.js"></script>
</body>
</html>
Edit:
Added my comment from above.
Why do you use two nested ng-repeats? I guess one object of the array should be one row in the table. Therefore
<tr ng-repeat="item in data">
...
<td>{{item.search_name}}</td>
...
</tr>
should work. Unless you need the keys of the object, than you need (key, value).