nested ng-repeat with 2 json data sources - angularjs

This is going to be complicated to explain, so please bear with me.
The task: To repeat json data in a table. (list of products, last cell is a button).
The problem: On clicking the button, another repeated list of rows appears under the product (second data-repeat, accessories of the products) but must match the product.
Now i can get the first part. I can even ng-repeat the second part, and the ng-click. However, every button repeats the same thing. I know that $index probably can be used here, i just dont understand how.
So how do i get the accessories for each individual product, to only show when the product button is clicked?
Example: Product 1 has 5 accessories. Product 2 has 1 accessory. If i click the product 1's button, 5 accessories show underneath it. If i click the product 2's button, 1 accessory shows below it.
Code:
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-12" style="padding:0px;">
<table class="table table-bordered" ng-controller="tableCtrl_1" ng-switch="test">
<tr style="height:70px;background-color:#0C4791;">
<th style="text-align:center;color:white;vertical-align:middle;">Flexi Floor/Low Wall</th>
<th style="text-align:center;color:white;vertical-align:middle;">Cooling</th>
<th style="text-align:center;color:white;vertical-align:middle;">Heating</th>
<th style="text-align:center;color:white;vertical-align:middle;">Nominal Capacities(cooling/heating)</th>
<th style="text-align:center;color:white;vertical-align:middle;">Pipe Length</th>
<th style="text-align:center;color:white;vertical-align:middle;">List Price</th>
<th style="text-align:center;color:white;vertical-align:middle;">Quantity</th>
</tr>
<tr ng-repeat-start = "getdata in getdata | filter:'Flexi Floor/Low Wall':true">
<td style="vertical-align:middle;text-align:center;">{{getdata.model_no_from}} + {{getdata.model_no_to}}</td>
<td style="vertical-align:middle;text-align:center;">{{getdata.cooling}}</td>
<td style="vertical-align:middle;text-align:center;">{{getdata.heating}}</td>
<td style="vertical-align:middle;text-align:center;"><span style="color:blue">{{getdata.nominal_cooling}}</span><span style="color:red;">{{getdata.nominal_heating}}</span></td>
<td style="vertical-align:middle;text-align:center;">{{getdata.pipe_length}}</td>
<td style="vertical-align:middle;text-align:center;"><span style="font-weight:bold;">{{getdata.system_listPrice | currency: "£"}}</span></td>
<td style="vertical-align:middle;text-align:center;"><button class="btn btn-default btn-large btn-block" ng-click="showDetails = ! showDetails">Select</button></td>
</tr>
<tr ng-repeat-end ng-class="{ 'hidden': ! showDetails }" >
<!--<td style="vertical-align:middle;text-align:center;">{{getdata_2.sales_description}}</td>
<td style="vertical-align:middle;text-align:center;">{{getdata_2.list_price}}</td> -->
<td colspan="7" style="text-align:center;vertical-align:middle;">test 1</td>
</tr>
</table>
</div>
</div>
</div>
</body>
And the controller:
testApp.controller('tableCtrl_1', function($scope, $http, ajaxServices, secondaryServices){
getdata();
function getdata(){
$http.post("angular_data.php").success(function(data){
$scope.getdata = data;
});
};
ajaxServices.getProducts().success(function(data){
$scope.getdata = data
});
secondaryServices.getProducts_2().success(function(data){
$scope.getdata_2 = data
});
});
Services:
testApp.factory('ajaxServices', function($http){
return {
getProducts: function(){
return $http.get('angular_data.php', {data: {}})
}
}
});
testApp.factory('secondaryServices', function($http){
return {
getProducts_2: function(){
return $http.get('angular_data_2.php', {data: {}})
}
}
});
Pardon the inline-styling, just easier for me while testing.

Related

Angularjs ng-repeat doesn't work as expected

I have an Angularjs controller(Angularjs 1.5.6) which calls a function from a python script, which returns an array of elements. I am trying to do an ng-repeat so that they appear in the table but for some reason, it doesn't show the elements of the array.
The 'Go' button in the html template triggers the function getSID which makes an HTTP call to a python script that returns an array. At the same time, the function also sets the scope, showval to true such that the table in the html appears only after the button is clicked.
<script>
angular.module('navigator', [])
.controller('HomeCtrl', function($scope, $http) {
$scope.getSid = function (sid) {
console.log(sid);
$http({
method: 'POST',
url: '/getMachine',
data: {sid:$scope.sid}
}).then(function(response) {
$scope.machines = [];
var object1 = response.data;
$scope.machines.push(object1);
//console.log(object1);
console.log($scope.machines);
$scope.showval = true;
}, function(error) {
console.log("hello");
console.log(error);
});
};
})
HTML code:
<div class="input-group mb-3 input-group-lg">
<div class="input-group-prepend">
<span class="input-group-text">Enter the SID</span>
</div>
<input type="text" class="form-control" ng-model="sid">
<button type="button" class="btn btn-outline-secondary" ng-click="getSid(sid)" ng-model="show" >
GO!
</button>
</div>
<div ng-show="showval">
<table class="table table-dark" >
<thead>
<tr>
<th scope="col">SID</th>
<th scope="col">Cluster</th>
<th scope="col">Node</th>
<th scope="col">Physical ip</th>
<th scope="col">Logical ip</th>
<th scope="col">Logical Host</th>
<th scope="col">Physical Host</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in machines">
<td>{{item}}</td>
</tr>
</tbody>
</table>
</div>
I googled ng-repeat and so several examples in plunker and I am following the same code but my code doesn't seem to work. Would be grateful for any assistance. Thanks for your time.
Your need to enclose track by $index within quotes as well,
<tr ng-repeat="item in machines track by $index">
Guilty of not posting the complete details. I was working with python flask and realized that the conflict is due to Jinja2.
I had to use the {%raw} {%end raw} so that Jinja2 processes it as an html.
More details in this Link
Now my code looks like this and ng-repeat is working.
{% raw %}
<tbody>
<tr ng-repeat="item in machines" >
<td>{{item}}</td>
</tr>
</tbody>
{% endraw %}

dirPagination numbers not change when ng-model search put something

At first, I'm using dirPagination. The problem is that when I search something, it's filtered correctly, but pagination number not change and also show all last number in pagination without any change and I see some page is empty because it does filter but page number is show.
<div data-ng-controller='productsController'>
<form `class='form-inline'>
<div class='form-group'>
<label>search</label>
<input type='text' data-ng-model='search' class='form-control' placeholder='search' />
</div>
</form>
<table class='table table-striped'>
<thead>
<tr>
<th>#</th>
<th>product</th>
<th>imet</th>
</tr>
</thead>
<tbody>
<tr dir-paginate='product in products|itemsPerPage:12|filter:search|orderBy:sortKey:reverse'>
<td>{{product.id}}</td>
<td>{{product.productName}}</td>
<td>{{product.time}}</td>
</tr>
</tbody>
</table>
<dir-pagination-controls max-size='10' direction-links='true' boundary-links='true' >
</dir-pagination-controls>
<script>
(function(){
var app = angular.module('products', ['angularUtils.directives.dirPagination']);
app.controller('productsController', function($scope, $http){
$scope.products = [];
$http.get('/products/json').success(function(data){
$scope.products= data;
});
});
})();
</script>
</div>
itemsPerPage must be the last filter, as below:
<tr dir-paginate='product in products | filter: search | orderBy: sortKey: reverse | itemsPerPage: 12'>
For more explanation, check it on FAQ on michaelbromley/angularUtils/.

AngularJS: should I choose what to print in the view or the controller?

I have a user info view where I have a table with some user data, which I get asynchronously from the backend. I don't want to print every field of this object.
What's the better practice, to pick the data directly in the template or to generate an object in the controller and then use an ngRepeat in the template?
If I wanted to do more complex stuff, like printing the user groups as an html list, which would be the better option then?
Example 1: Pick data in template
// controller.js
backendApi.userInfo($stateParams.user)
.then(function (user){
vm.user = user;
});
<!-- view.html -->
<table class="table table-condensed">
<tr>
<th class="col-xs-2 col-md-1">ID</th>
<td class="col-xs-10 col-md-11">{{vm.user.id}}</td>
</tr>
<tr>
<th class="col-xs-2 col-md-1">Name</th>
<td class="col-xs-10 col-md-11">{{vm.user.name}} {{vm.user.surname}}</td>
</tr>
<tr>
<th class="col-xs-2 col-md-1">Status</th>
<td class="col-xs-10 col-md-11">{{vm.userEnabledString(vm.user)}}</td>
</tr>
<tr>
<th class="col-xs-2 col-md-1">Groups</th>
<td class="col-xs-10 col-md-11">{{vm.user.groups.join(", ")}}</td>
</tr>
</table>
Example 2: Pick data in controller and use ngRepeat in the view.
// controller.js
backendApi.userInfo($stateParams.user)
.then(function (user){
// user has more fields that I don't need to print.
vm.user = {
"ID": user.id,
"Name": user.name + " " + user.surname,
"Status" : userEnabledString(user),
"Groups": user.groups.join(", ")
}
});
<!-- view.html -->
<table class="table table-condensed">
<tr ng-repeat="(key, value) in vm.user">
<th class="col-xs-2 col-md-1">{{key}}</th>
<td class="col-xs-10 col-md-11">{{value}}</td>
</tr>
</table>
The function userEnabledString prints a textual representation of a boolean.
Why don`t you use existing Angular control instate of re-engineering unless it does not suffice your needs.
Please refer below control, it easy to use.
http://angular-ui.github.io/ui-grid/

Getting key value pairs from json reponse into angular js

How do I map the json response to the table in html page.
Angularjs Controller:
app.controller('tableController', function ($scope,$http)
{
$scope.customerTable = [];
$scope.getTable = function ()
{
$http.get('<%=request.getContextPath()%>/GetTable.do').success(function (data)
{
$scope.customerTable = data;
// console.log($scope.customerTable);
});
};
});
html code:
<div ng-controller="tableController">
<!--<p>Click <a ng-click="getTable()">here</a> to load data.</p>-->
<table>
<tr>
<th>Card Number</th>
<th>First Name</th>
<th>Opening Balance</th>
<th>Withdrawal</th>
<th>Deposit</th>
<th>Closing Balance</th>
<th>Tx Date</th>
<th>Usage_Type</th>
</tr>
<tr ng-repeat="data in customerTable ">
<td>{{data[0]}}</td>
</tr>
</table>
<br>
<button class="form-control btn btn-success" type="submit" ng-click="getTable()">Load Table Data</button>
</div>
The response is in one array with key, value pairs. Do I have to modify the ng-repeat?
Here is the json response:
[{"TXDATE":"1-Aug-14","FIRST_NAME":"MOSES","USAGE_TYPE":"HOTELS/MOTELS/RESORTS","WITHDRAWAL":"15200","DEPOSIT":"0","CARD_NUMBER":"AL98****66325","CLOSING_BAL":"-362764.96","OPENING_BALANCE":"0"}]
You can use the fields in every object:
<tr ng-repeat="data in customerTable ">
<th>{{data.FIRST_NAME}}</th>
<th>{{data.CARD_NUMBER}}</th>
...
</tr>
Perhaps you could use a directive for this kind of table related iterations.
Use the attributes. it should be:
<tr ng-repeat="data in customerTable ">
<td>{{data.TXDATE}}</td> <!-- result: 1-Aug-14 -->
</tr>
and so on.
Yes, you have to modify it.
<tr ng-repeat="data in customerTable ">
<td>{{data['CARD_NUMBER']}}</td>
<td>{{data['TXDATE']}}</td>
<td>{{data['OPENING_BALANCE']}}</td>
...
</tr>

Loading text before data is loaded AngularJS

Does anyone have a clue how to create a loading text before angular loads data in to a list?
I have this code for getting info from different subwebs (in sharepoint). But before (or while) the list is loaded I want to display a text "Loading...":
context.executeQueryAsync(Function.createDelegate(this, function () {
var webs = this._webs.getEnumerator();
while (webs.moveNext()) {
var subWeb = webs.get_current();
$scope.sites.push({
title: webs.get_title(),
});
$scope.$apply();
}
}
}),
HTML:
<div ng-controller="MainCtrl">
<table>
<thead>
<tr>
<th>
Site
</th>
<th>
Created
</th>
</tr>
</thead>
<tbody ng-repeat="site in sites">
<tr>
<td>
{{site.title}}
</td>
<td>
{{site.created | date:dateFormat}}
</td>
</tr>
</tbody>
</table>
<tbody ng-if="sites.length == 0">
<tr>
<td>
<img src="loading.gif">
</td>
</tr>
</tbody>
<tbody ng-repeat="site in sites" ng-if="sites.length > 0">
<tr>
<td>
{{site.title}}
</td>
<td>
{{site.created | date:dateFormat}}
</td>
</tr>
</tbody>
This produce 2 watchers but it will help.
some links of loading indicator : angular-spinner or angular-sham-spinner
also BLOG detailing on how the spinner works with angularjs
and in case you want to implement it yourself, below code will get you started...
app.directive("spinner", function(){
return: {
restrict: 'E',
scope: {enable:"="},
template: <div class="spinner" ng-show="enable"><img src="content/spinner.gif"></div>
}
});
warning : i havent tested the code but directive wont be more complex than this...

Resources