Creating check box grid using ng-repeat - angularjs

The Json structure,
[
{
"name": "module1",
"categories": [
{
"name": "cat1"
},
{
"name": "cat4"
}
]
},
{
"name": "module2",
"categories": [
{
"name": "cat3"
},
{
"name": "cat4"
}
]
},
{
"name": "module3",
"categories": [
{
"name": "cat1"
},
{
"name": "cat2"
},
{
"name": "cat4"
}
]
}
]
Using this Json structure, I need to display a grid of checkboxes as follows,
On click of any checkbox, I should be able to alert the corresponding category & module name. If each module has all four categories then I can easily use nested ng-repeat and display the structure (You can check it here. ). But here the number of categories differs for each module. Could you please suggest a way to implement this functionality?
Need to find the number of categories first and display it as the headers in the table
Display checkbox exactly at the right place

It is possible to have an ng-repeat iterate over the result of a function - in contrast to an array field in the scope - like this:
<tr ng-repeat="module in getAllModules()">
<td ng-repeat="cat in getAllCategories()">
<!-- display checkbox here if required -->
</td>
</tr>
I think it should be clear how to implement the two methods. However, you have to consider the performance overhead involved because the total set of modules and categories is calculated over and over again.

I think lex answer is corrrect. If I understood his solution right,the getAllCategories method is the interesting part. It has to return ALL categories, while getAllModules can still return your modules Array.
<tr ng-repeat="module in modules">
<td ng-repeat="cat in getAllCategories()">
<input type="check" ng-if="module.containsCat(cat)">
</td>
</tr>
with the containsCat method being something like
$scope.containsCat = function(module, cat){
for each(var moduleCat in module.categories ){
if(moduleCat.name === cat) return true;
}
return false;
}

Related

Angular access in controller to ng-model in nested ng-repeat

I have problem as in the topic. Using $parent in ng-model didn't help.
What I am trying to achieve is 2 clickable buttons to increase and decrease quantity field value by one and display summary (sum of each price*quantity) on the bottom of site.
var app = angular.module("mainApp", []);
app.controller("mainCtrl", function ($scope) {
$scope.list1 = [
{ "uniqueId": "1", "name": "cat1" },
{ "uniqueId": "2", "name": "cat2" }
];
$scope.list2 = [
{ "uniqueId": "1", "name": "prod1", "price": "10" },
{ "uniqueId": "2", "name": "prod2", "price": "20" },
{ "uniqueId": "3", "name": "prod3", "price": "30" }
];
// this one below doesn't work at all
// $scope.quantity[1] = 1;
$scope.inc = inc;
function inc(id) {
console.log(id); //works fine
// increase of exact quantity
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="mainApp">
<div ng-controller="mainCtrl">
<table ng-repeat="l1 in list1">
<tr>
<td>
{{l1.name}}
</td>
</tr>
<tr ng-repeat="l2 in list2">
<td>name: {{l2.name}},</td>
<td>price: {{l2.price}},</td>
<td>quantity wanted: <input ng-model="quantity[l2.uniqueId]"><button ng-click="inc(l2.uniqueId)" type="button">+</button></td>
</tr>
</table>
{{quantity}}<!-- sum of all quantities * prices -->
</div>
<div>
Keep in mind that there is mulitple way to solve this kind of problem, here is the grand line I see to do it and an example for each step:
Store your quantity somewhere and initialise it, for example in your product object, example in your controller:
{ "uniqueId": "1", "name": "prod1", "price": "10", quantity : 1 },
Create a function to increase and an other to decrease the quantity of a product by his id, example in your controller:
function increaseQuantity(id){
// Get your product in the list with a loop
// If the product exists
// Increase his quantity
}
function decreaseQuantity(id){
// Get your product in the list with a loop
// If the product exists
// Decrease his quantity
}
$scope.increaseQuantity = increaseQuantity;
$scope.decreaseQuantity = decreaseQuantity;
Call the right methods in your buttons, example in your view:
<td>
quantity wanted: {{l2.quantity}}
<button ng-click="increaseQuantity(l2.uniqueId)" type="button">+</button>
<button ng-click="decreaseQuantity(l2.uniqueId)" type="button">-</button>
</td>

Add a button to show additional data in data tables

i am not much familiar with Data Tables but by following the examples provide i manged to load the data set to my table via an json. now my problem is i have some additional data to show when a button in a row clicked.lets say i view club details when i click on show members button which is in each raw i need to show members details from the json file.How can i achieve this.Sorry if i am repeating a question but couldn't find one here.if you can provide me certain resources which address a slimier problem i'll appreciate. Thanks!
my json seems like.
{
"data": [
{
"club": [
"xxxxx",
"xxxxx"
],
"members":[{"a":{"fname":"AAA","lname":"BBB"},"b":{"fname":"AAA","lname":"BBB"},"c":{"fname":"AAA","lname":"BBB"}}],
"address": [
"xxxx",
"xxxxx",
"xxxxxx"
],
"district": "xxxxx",
"established": "xxxx"
},
{
"club": [
"xxxxx",
"xxxxx"
],
"members":[{"a":{"fname":"AAA","lname":"BBB"},"b":{"fname":"AAA","lname":"BBB"},"c":{"fname":"AAA","lname":"BBB"}}],
"address": [
"xxxx",
"xxxxx",
"xxxxxx"
],
"district": "xxxxx",
"established": "xxxx"
}
]}
my script to load data as follows.
<script>
$(document).ready(function() {
$('#example').DataTable( {
"ajax": "spellData.json",
"columns": [
{ "data": "club[, ]" },
{ "data": "address.0" },
{ "data": "members[, ]" },
{ "data": "district" },
{ "data": "established" },
{ "data": "address.2" },
{ "data": "address.1" }
]
} );
} );
</script>
my table is as follows.
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Club Name</th>
<th>Area</th>
<th>Members</th>
<th>District</th>
<th>Estb.</th>
<th>Address</th>
<th>Town</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Club Name</th>
<th>Area</th>
<th>Members</th>
<th>District</th>
<th>Estb.</th>
<th>Address</th>
<th>Town</th>
</tr>
</tfoot>
</table>
here if i can use a dialog to load member data its easy because i may need to add some columns too.How i can achieve something like this?HEre is a jsfiddle if you need..
You were nearly there but the alert was due to reinitialising the child DataTable. If you initialise it on page load and then interact with it when the button is clicked it's much better as you'll then not have to check to see if it's been initialised already:
var e = $('#sub_table').DataTable({
"columns": [{
"data": "fname",
"title": "First Name"
}, {
"data": "lname",
"title": "Last Name"
}]
});
Then, when your button is clicked you can clear the table, add the rows (might be better to have members being an array here, then you could add them all in one go using rows.add() which accepts an array rather than an object) and finally draw it again. As things stand this works:
$('table.table').on('click', '.mybutton', function() {
e.clear();
$.each(example.row($(this).parents('tr')).data().members, function(k, v) {
e.row.add(v);
});
e.draw();
});
Working JSFiddle, hope that helps.

Using Angular Typeahead on Nested Objects

I'm trying to use Angular Bootstrap Typeahead on an array of nested objects and I cannot figure out how to write out the typeahead.
My objects in my array are like so:
{
"category": "Locations",
"regions": [
{
"name": "Northeast",
"category": "region",
"states": [
{
"name": "New York",
"category": "state"
"cities": [
{
"name": "Syracuse",
"category": "city"
}
]
}
]
}
I only want to return the name values. So how would I go about writing this out?
I currently am writing <input ... typeahead=" filter.name for filter in filters| filter:$viewValue | limitTo:5">
Rather than using "in filters" just do something like "in transformFilters()"
$scope.transformFilters = function () {
// Loop over filters and create an array of
{name: name, category:cat}
return my new array
}

How do I hide the square brackets in my template expressions?

I have a simple JSON object in my models
whitelist = [
{
"name": "Whitelist #1",
"permissions": [
"production_sdk",
"source_sdk",
"service"
],
},
{
"name": "Whitelist #2",
"permissions": [
"production_sdk",
"service"
],
},
{
"name": "Whitelist #3",
"permissions": [
"production_sdk",
"source_sdk"
],
}
]
In my html I have {{ whitelist.permissions }}, but the HTML displays the values with brackets - ['production_sdk', 'source_sdk'].
How can I display the HTML so that there are no brackets?
whitelist.permissions is an array, how do you want that to be displayed in your html? You should probably create a simple filter that takes an array and outputs what you want, but you could just change your html to do this to get a comma-separated list:
{{ whitelist.permissions.join(', ') }}
Another option, especially if you want to style each permission, is to use ng-repeat and html elements:
<span ng-repeat="permission in whitelist.permissions"><span ng-if="$index != 0">, </span>{{ permission }}</span>

ng-repeat repeating by letters wise

I have multiple level json that need to show using ng-repeat but i am getting issues
JSON
$scope.product = {
"product": [
{
"name": "0001",
"tagline": "Scrub peached 60% cot 40% poly\r\ns/s v neck scrub uniform w/ 1 chest pkt"
}
],
"sizes": [
"XXL",
"XXXL",
"XS",
"XL",
"S",
"M",
"L"
],
"colors": [
{
"name": "WHITE",
"image": "/kalypso/commonsController.do?param=imageLoader&imageName=1239378389537_white1.JPG"
}
],
"images": [
{
"big": "/kalypso/commonsController.do?param=imageLoader&imageName=2010_08/1281620375516_UT01.jpg",
"small": [
"/kalypso/commonsController.do?param=imageLoader&imageName=2009_07/D0001-b.jpg"
],
"thumb": "/kalypso/commonsController.do?param=imageLoader&imageName=2010_08/1281620375516_UT01.jpg"
}
]
}
AngularJS
$scope.productsImages = $scope.product.images[0].thumb;
$scope.productsImgSmall = $scope.product.images[0].small;
$scope.productsImgBig = $scope.product.images[0].big;
$scope.productsColors = $scope.product.colors[0].cname;
$scope.productsColorsImages = $scope.product.colors[0].image;
$scope.productsSizes = $scope.product.sizes;
$scope.productsName = $scope.product.product[0].name;
$scope.productsTag = $scope.product.product[0].tagline;
$scope.productsPrice = $scope.product.product[0].price;
$scope.productsId = $scope.product.product[0].prdId;
console.log($scope.productsColors);
It is repeating the color name each word and if array length is zero I am getting duplicate error messages. Please help on this.
Error: [ngRepeat:dupes] http://errors.angularjs.org/1.3.0/ngRepeat/dupes?p0=color%20in%20productsColors&p1=string%3AT&p2=%22T%22
i would look into track by $index if you do not have a unique id on your json object
item in items track by $id(item)
or
item in items track by $index
if you want angular to deal with it
instead of array [i] value use like this
$scope.productsImages = $scope.product.images;
HTML
<ul>
<li ng-repeat="prd in productsImages">
{{prd.thumb}}
</li>
</ul>
use repeat function for all key
another Example
$scope.data.colors = $scope.product.colors
<ul>
<li ng-repeat="color in product.colors">
{{color.name}}
{{color.image}}
</li>
</ul>

Resources