I am working on a angular project. i have a scenario where i need to list some details in a page of the application.I have a service call in the page which returns the following json structure. i want to loop through this json structure to list few of the data in the response.
[
{
"ProductDetails": [
{
"ProductType": "Application1",
"Name": "Product1",
"New": false,
"Category": "product",
"Country": "India",
"description": "Description for Product1",
"Favourite": false,
"settings": {
"WebsiteFlag": true,
"SmsFlag": false,
"EmailFlag": true
}
}
]
},
{
"ProductDetails": [
{
"ProductType": "Application2",
"Name": "Product2",
"New": true,
"Category": "product",
"Country": "India",
"description": "Description for Product2",
"Favourite": true,
"settings": {
"WebsiteFlag": false,
"SmsFlag": false,
"EmailFlag": true
}
}
]
}
]
JS
$ctrl.getSettings = function () {
var url = "http://localhost:3000/json/settings-updated.json";
rsicontext.getData(url).then(function (response) {
$ctrl.Settings = response.data;
});
}
HTML
<tbody>
<tr data-ng-repeat="app in $ctrl.Settings" class="content-box">
<td data-ng-bind="app.ProductDetails.ProductType"></td>
<td data-ng-bind="app.ProductDetails.Name"></td>
<td><ng-checkbox data-checked="app.SmsFlag" rounded="true"></ng-checkbox></td>
<td><ng-checkbox data-checked="app.EmailFlag" rounded="true"></ng-checkbox></td>
</tr>
</tbody>
I am trying to list the Product Type, Name, EmailFlag and SmsFlag. How can i loop through the json structure to list the data.
Simply go over the response and build a new array from the fields you need. Like so:
var d = [];
for( vari=0;i< response.data.ProductDetails.length; ++i) {
var curr= {
ProductType: response.data.ProductDetails[i].ProductType,
Name: response.data.ProductDetails[i].Name
}
d.push(curr);
}
$ctrl.Settings = d;
To manipulate object or array I always use a library called underscore.js
This can help you to do what you want.
var plucked=_.pluck($ctrl.Settings, 'ProductDetails');
This function will return an array of object. Then you can loop it.
https://jsfiddle.net/wz2njukj/
You can achieve this throw ng-repeat
<div ng-repeat="d in data[0].ProductDetails[0]">
{{ d.SmsFlag }} {{ d.WebsiteFlag}} {{d.EmailFlag}}
</div>
Look this and get data as you want.
PlunkerHere
ProductDetails contains an array, so you would have to nest ngRepeats
<span data-ng-repeat="detail in app.ProductDetails">
If you know that ProductDetails will only have one element it would be best to change the structure that is being generated if you can. If not you can access it in markup
<tbody>
<tr data-ng-repeat="app in $ctrl.Settings" class="content-box">
<td data-ng-bind="app.ProductDetails[0].ProductType"></td>
<td data-ng-bind="app.ProductDetails[0].Name"></td>
<td><ng-checkbox data-checked="app.ProductDetails[0].settings.SmsFlag" rounded="true"></ng-checkbox></td>
<td><ng-checkbox data-checked="app.ProductDetails[0].settings.EmailFlag" rounded="true"></ng-checkbox></td>
</tr>
</tbody>
Or you can massage the data in your controller before passing it off to the view.
$ctrl.Settings = response.data.map(products=>products.ProductDetails[0])
Related
I am using table for showing the datas and for data I am using Api.
Api data looks like::
{
"data": [
{
"id": "1",
"name": "name1",
"label": "label1"
},
{
"id": "2",
"name": "name2",
"label": "label2"
},
{
"id": "3",
"name": "name3",
"label": "label3"
}
]
}
html code
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Label</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of sample;">
<td>{{data.id}}</td>
<td>{{data.name}}</td>
<td>{{data.label}}</td>
<tr>
<tbody>
<table>
I need the 10 table rows statically(fixed). The table data is from API. For exanple ,Api contains 2 data... Then UI table should be with 2 rows of data and balance with emply rows... but there should display 10 rows(Mandatory)
which means in UI i want 10 rows with data from Api and balance should be empty.
You can fix in view layer, ts layer or even backend API layer (Not really recommended).
In view layer if you loop over your data, you can calculate if your data's size goes over arbitrary threshold and if not loop again to display as many empty rows as possible.
In ts layer, when you receive data from api you can modify variable you pass to your view by adding to an array as many empty items as you need.
What's important if you use null, then you have to check for it with for example elvis operator.
I would advise agains adding to an array an object with all properties set to null, because then these are not so easily distinguishable from valid data from API and you can for instance make some rows interactive, even though they should not be.
const dataFromApi = [{ "id": "1", "name": "name1" }, { "id": "2", "name": "name2" }]
const minRowsNumber = 10;
const diff = minRowsNumber - dataFromApi.length;
const viewTableData = diff > 0 ? dataFromApi.concat(new Array(diff).fill(null)) : dataFromApi;
console.log(viewTableData)
Example in AngularJs (No Angular in SO Snippets, but it is the same principle)
angular.module('example', [])
.controller('ExampleController', function ExampleController() {
const dataFromApi = [{ "id": "1", "name": "name1" }, { "id": "2", "name": "name2" }]
const minRowsNumber = 10;
const diff = minRowsNumber - dataFromApi.length;
this.viewTableData = diff > 0 ? dataFromApi.concat(new Array(diff).fill(null)) : dataFromApi;
});
table {
border-collapse: collapse;
}
td, th {
border: 1px solid black
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="example" ng-controller="ExampleController as example">
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in example.viewTableData track by $index">
<td>{{row ? row.id : ' '}}</td>
<td>{{row ? row.name : ' '}}</td>
</tr>
</tbody>
</table>
</div>
I'm trying to fill a HTML table with JSON data. I'm using dynatable plugin.(No specific reason to use this. Just that I bumped on to this & found it's UI to be appealing).
JSON data sample returned by server
[{"DATE":"2015-12-15","TYPE":"AAA","NAME":"asdasd"},{"DATE":"2015-12-15","TYPE":"BBB","NAME":"dsfsdfsdfsdf"},{"DATE":"2015-12-15","TYPE":"AAA","NAME":"reterter"},{"DATE":"2015-12-15","TYPE":"CCC","NAME":"ertertertert"}]
Code below -
function jsDataPlot(chartProps) {
// Get the array from the element:
var graphPropsStore = chartProps;
// Loop through the array with the jQuery each function:
$.each(graphPropsStore, function (k, graphPropsStoreProperty) {
// The makeCall function returns a ajaxObject so the object gets put in var promise
var dbResAjx = getResultFromSql(k);
// Now fill the success function in this ajaxObject (could also use .error() or .done() )
dbResAjx.success(function (response) {
console.log(response);
// myRecords = JSON.parse(response.text());
$('#tableIdToFill').dynatable({
dataset: {
records: $.parseJSON(response)
}
});
});
dbResAjx.error(function (response) {
console.log(response);
});
});
}
The problem I have is, tough the JSON response is coming back from the server fine, the table is getting fileld with undefined
Here's the HTML code for the table
<body id="htmlDataTable">
<table id="tableIdToFill" class="display" cellspacing="0" width="98%">
<thead>
<tr>
<th>DATE</th>
<th>TYPE</th>
<th>NAME</th>
</tr>
</thead>
<tfoot>
<tr>
<th>DATE</th>
<th>TYPE</th>
<th>NAME</th>
</tr>
</tfoot>
</table>
</body>
I'm following the article here
Issue is with name of the properties, they need to start with lower-case.
var jsonData = `[
{
"date": "2015-12-15",
"type": "AAA",
"name": "asdasd"
},
{
"date": "2015-12-15",
"type": "BBB",
"name": "dsfsdfsdfsdf"
},
{
"date": "2015-12-15",
"type": "AAA",
"name": "reterter"
},
{
"date": "2015-12-15",
"type": "CCC",
"name": "ertertertert"
}
]`;
//console.log(jsonData);
var response = JSON.parse(jsonData);
console.log(response);
$('#tableIdToFill').dynatable({
dataset: {
records: response
}
});
See this jsFiddle
so I'm working with a basic product category model to get my head around filtering and I can't figure out how to extract a property value from one object within an array while repeating through another.
A simplified version of my category array, which is in scope, looks like this. I can output their names with the preceding directive and the results are as expected:
[{
"_id": "TY76",
"name": "Planes"
}, {
"_id": "887T",
"name": "Trains"
}, {
"_id": "A0K4",
"name": "Autos"
}]
<p ng-repeat="category in product.categories "> {{ category.name }}</p>
And here is a simplified product, also in scope, which may contain the ID of one or more categories. In this case, Bobble Head belongs to both Planes and Autos:
{
"_id": "9876",
"name": "Bobble Head",
"cats": "['TY76','A0K4']"
}
Now, here is where I'm having a hard time. I need to output the category names with the product. I can output the IDs no problem via:
<p ng-repeat="cat in product.cats ">{{ cat }}</p>
But that's of no use to the end user but I have no idea how to end up with something like:
Product: Bobble Head | Categories: Planes, Autos
I don't have the autonomy to add the category name to each product and I've tried a bunch of different filtering approaches but I don't think I'm wording my question right or something because I'm not finding much on the interwebs about this.
Any ideas?
Sounds like you want to build up a lookup for category id to category name:
var categories = [{
"_id": "TY76",
"name": "Planes"
}, {
"_id": "887T",
"name": "Trains"
}, {
"_id": "A0K4",
"name": "Autos"
}];
// build a category lookup id -> name
var categoryLookup = {};
categories.forEach(function(category) {
categoryLookup[category._id] = category.name;
});
Here's a full working fiddle: http://jsfiddle.net/02qadem7/1/
You can create a key-pair object where the key is the id and the value is the name of the category:
var categoriesArray = [{
"_id": "TY76",
"name": "Planes"
}, {
"_id": "887T",
"name": "Trains"
}, {
"_id": "A0K4",
"name": "Autos"
}];
$scope.categoriesMap = {};
categoriesArray.forEach(function(category) {
$scope.categoriesMap[category._id] = category.name;
});
Then in your view you can access the category name like this:
<div ng-repeat="product in products">
<strong>Product: </strong> {{product.name}} |
<strong>Categories: </strong> <span ng-repeat="category in product.cats">
{{categoriesMap[category]}}
</span>
</div>
Here's a plunkr: http://plnkr.co/edit/BpBcCizzU2Vh8VPniiHA?p=preview
I sugest using a custom filter on categories array.
myApp.filter('byCategoryIds', function() {
return function(categories, catIds) {
return categories.filter(function(item) {
return (catIds.indexOf(item._id) != -1);
});
};
});
Then you can iterate on categori array sending ids array like so:
<b>Product:</b>
{{product.name}};
<b>Categories:</b>
<span ng-repeat="cat in categories | byCategoryIds: product.cats">{{ cat.name }}, </span>
I am working with a project, where I need to collect multiple items from user and send it to the server. There is list on my view, where user can click and select the items. My HTML looks like this,
HTML
<div ng-repeat="topicList in searchCtrl.topic">
<div ng-repeat="topicTerm in topicList">
<p>{{topicTerm.number}}  {{topicTerm.name}}</p>
<div ng-repeat="subTopic in topicTerm.subTopics">
{{subTopic.number}}  {{subTopic.name}}
</div>
</div>
</div>
I have used anchor tag, there user can click and at the same time I want the clicked items (which have also unique ID) collected in an Array or variable, which I need to send (these selected items) to the server via form submission.
This is how my controller looks like,
JavaScript Controller
angular.module('myApp').controller("searchController", function($log, searchService, $scope){
var self = this;
self.initializeSearch = function(){
self.searchEntry =
{
"contact":{
"person": "",
"organization": ""
},
"request": {
"input": "",
"language": "en"
},
"topicIds": []
};
// The POST request must looks like above
What I want is that the clicked subTopics IDs collects in an Array "topicIds : []" and I could successfully send the POST request mentioned above. The searchService is a Angular service which helps to get Topics from server and also to POST user input to the server.
This is how my JSON looks like,
JSON API
{
"TopicList" :[
{
"id": "798790fa-78c8-4f00-8179-9e70f40adb14",
"name": "Topic1",
"number": 1.0,
"subTopics": [
{
"id": "82c90f2e-deac-4fa4-80f4-d077edacc2dc",
"name": "data1.1",
"number": 1.1
},
{
"id": "0f0c2b89-6dae-4f60-90f8-df49d96b9af9",
"name": "data1.2",
"number": 1.2
},
{
"id": "131b68b6-1f45-477f-9b0f-8ac80c5b4f4e",
"name": "data1.3",
"number": 1.3
},
{
"id": "16c8f46d-d20c-48f9-a0c0-e3989763082b",
"name": "data1.4",
"number": 1.4
}
]
},
{
"id": "9ed3fee0-5347-4f00-9b56-721b61439f88",
"name": "Topic2",
"number": 2.0,
"subTopics": [
{
"id": "eec13511-1408-4f4b-be6f-8b5a8b6ea28b",
"name": "data2.1",
"number": 2.1
},
...
]
},
...
]
}
How to write a function or array which collects the IDs via ng-click event?
Thanks in Advance.
No need to use an $event, simple pass the subTopic.id, or whatever, in your ng-click, like ng-click="searchCtrl.select(subTopic)"
And then in your controller, you could have:
angular.module('myApp').controller("searchController", function($log, searchService, $scope){
var self = this;
var subTopicIds = []; // array to hold subTopicIds
self.select = function(subTopic) {
subTopicIds.push(subTopic.id);
}
self.initializeSearch = function(){
self.searchEntry =
{
"contact":{
"person": "",
"organization": ""
},
"request": {
"input": "",
"language": "en"
},
"topicIds": subTopicIds // use the object created previously
};
...
You can get an ID in angular like this.
<div ng-click="recordClick($event)">Click</div>
That will feed the click event into the recordClick method, where you can then call it's target property (i.e. the div it was invoked on) and push it in the array.
$scope.clickArray = [];
$scope.recordClick = function(event){
clickArray.push(event.target);
}
I solved this problem by passing subTopics ID in ng-click as a parameter. And as per the requirement I need to call also another event while user click, which I passed as a second argument. So, now both the events works as I wanted via single ng-click.
Here is my updated code,
HTML
<div ng-repeat="topicList in searchCtrl.topic">
<div ng-repeat="topicTerm in topicList">
<p>{{topicTerm.number}}  {{topicTerm.name}}</p>
<div ng-repeat="subTopic in topicTerm.subTopics">
{{subTopic.number}}  {{subTopic.name}}
</div>
</div>
</div>
And here is my controller,
Controller
angular.module('myApp').controller("searchController", function($log, searchService, $scope){
var self = this;
var subTopicIDs = [];
self.select = function(TopicIDs, event){
subTopicIDs.push(TopicIDs);
$(event.target).addClass('selor'); // This is class which changes the background color of the clicked item
console.log(TopicIDs);
}
self.initializeSearch = function(){
self.searchEntry =
{
"contact":{
"person": "",
"organization": ""
},
"request": {
"input": "",
"language": "en"
},
"topicIds": subTopicIDs
};
This is how it solved my problem.
Btw, Thank you Tom and OceansOnPluto.
I am new to AngularJS and I'm having problems doing a reusable generic filter.
Let's say I have a colors, types, and list objects as seen below (New JSON).
I want to make a generic filter that will take colors and types objects and filter the list object without having to use the string match as filter.
For now I did specific filters by strings as seen below.
I will have a lot of information in these objects and I don't want to update the controller each time a new property is being included in the JSON.
How do I associate the number to its specific string value?
Old JSON
[
{
"id": 1,
"name": "Spike",
"type": "dog",
"color": "gray"
},
{
"id": 2,
"name": "Tom",
"type": "cat",
"color": "blue"
},
{
"id": 3,
"name": "Butch",
"type": "cat",
"color": "black"
}
]
New JSONs
// colors
[
{"gray": 1},
{"black": 2},
{"blue": 3},
]
// types
[
{"dog": 1},
{"cat": 2}
]
// data list
[
{
"id": 1,
"type": 1,
"name": "Spike",
"color": 1
},
{
"id": 2,
"type": 2,
"name": "Tom",
"color": 3
},
{
"id": 3,
"type": 2,
"name": "Butch",
"color": 2
}
]
Filters
<table class="table table-bordered table-condensed table-striped table-hover">
<thead>
<tr>
<th>
<a>
Filters:
</a>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in typeItems">
<td>
<label class="check">
<input type="checkbox" ng-model="typeFilterItems[item.type]">{{item.type}}
</label>
</td>
</tr>
<tr ng-repeat="item in colorItems">
<td>
<label class="check">
<input type="checkbox" ng-model="colorFilterItems[item.color]">{{item.color}
</label>
</td>
</tr>
</tbody>
</table>
List
<table class="table table-bordered table-condensed table-striped table-hover header-fixed">
<thead>
<tr>
<th>ID</th>
<th>Type</th>
<th>Color</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr class="list" ng-repeat="item in animals | filter:typeFilter | filter:colorFilter">
<td>{{item.id}</td>
<td>{{item.type}}</td>
<td>{{item.color}}</td>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
Controller
Animals.list().then(function (data) {
$scope.animals = data;
});
$scope.colorFilterItems = { 'black': true, 'gray': false, 'blue': false }; // doing this to have a predefined filter selection ... for now
$scope.colorItems = [{ name: 'black' }, { name: 'gray' }, { name: 'blue' }];
$scope.colorFilter = function (item) {
return $scope.colorFilterItems[item.color]
};
$scope.typeFilterItems = { 'dog': true, 'cat': false }; // doing this to have a predefined filter selection ... for now
$scope.typeItems = [{ name: 'black' }, { name: 'gray' }, { name: 'blue' }];
$scope.typeFilter = function (item) {
return $scope.typeFilterItems[item.type]
};
Since no one answered I eventually found a solution.
The answer to all this is to use lodash directly inside the service and create a filter method inside the promise that looks for the selected property inside the filter objects and compares them to the data we want to display.
filterAnimals = () => {
intersectedResults =
_.filter(animals,(animal: iAnimal) => {
var colors = _.find(colorLabels,(item: iFilter) => {
return (animal.color ? item.label === animal.color : item.label == null) && item.selected;
});
var types = _.find(typeLabels,(item: iFilter) => {
return (animal.type ? item.label === animal.type : item.label == null) && item.selected;
});
return colors && types;
});
return data;
};
After doing this I acces the filterAnimals() function from the controller and bind the checkbox filters to my data. When doing an ng-change on the checkbox this function executes and checks the filters against the data and it shows the data I need.