Get the parent index of the array angularjs - html

I searching and I found out that this code is what I need right now. But there is something wrong about it. When I clicked the alertme button it's alert is -1 which is wrong. When I click 1 Brick med it's alert -1 it should be 0 because the no and name is in sectionA. When I want t click 3 Frank Joemar Timbang it should alert 1 because he is in sectionB? Aney help? suggestions? TIA
var stud = angular.module("stud", []);
stud.controller("StudentsController", function ($scope) {
'use strict';
$scope.alertMe = function (studentGroup) {
alert($scope.students.indexOf(studentGroup));
};
$scope.sectionA = [
{
no:1,
name:'Brick Med',
},
{
no:2,
name: 'Colin Christopher',
},
];
$scope.sectionB = [
{
no:3,
name: 'Frank Joemar Timbang',
},
{
no:4,
name: 'Curtis Zaymond',
}
];
$scope.students = [
$scope.sectionA,
$scope.sectionB
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html data-ng-app="stud">
<head lang="en">
<meta charset="utf-8">
<title>Students</title>
</head>
<body data-ng-controller="StudentsController" data-ng-init="init()">
<div id="container">
</div>
<div class="container-table">
<table border="1" width="100%">
<thead>
<tr>
<td>Students</td>
<td>Alert</td>
</tr>
</thead>
<tbody ng-repeat="studentGroup in students">
<tr ng-repeat="student in studentGroup">
<td>{{student.no}} {{student.name}}</td>
<td><button ng-click="alertMe($parent.$index)">Alert me!</button></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

Okay so your problem is that you are using indexOf() when you want to just be using studentGroup as the index.
$scope.alertMe = function (studentGroup) {
alert($scope.students[studentGroup]); // returns object object in your array
alert($scope.students[studentGroup][0]); /// returns sectionA object1
alert($scope.students[studentGroup][0].name); /// returns sectionA object1 name
};
And I fixed up your html so it is easier to read but your original stuff should still work.
<tbody ng-repeat="studentGroup in students" ng-init="studentsIndex = $index">
<tr ng-repeat="student in studentGroup">
<td>{{student.no}} {{student.name}}</td>
<td><button ng-click="alertMe(studentsIndex)">Alert me!</button></td>
</tr>
</tbody>
If this isn't what you want and you really want to alert the index, let me explain how indexOf works. That method will take a search parameter, and that is used to search an array for that element data. It is returning -1 right now because you give it the index and it searches for that index as the element data in index 0 and 1. Steps: Does whatever index = $scope.sectionA , Nope move on, Does whatever index = $scope.sectionB, nope move on. Done, did not find search parameter return -1.

The problem is with the indexOf. studentGroup is set correctly to 0 for the first 2 rows and 1 for the next 2. If you want the section array you should use
$scope.alertMe = function (studentGroup) {
alert($scope.students[studentGroup]);
};

Related

Angular Doesn't Update ng-show

I have a table from which I have the representation of data that gets updated every 10 seconds or so, represented by the "current" list. As you can see in the code snippet below, the two ng-show's depend on the Status value of an object. I know that the list is getting updated with new values, so that the second ng-show should be showing and not the first, but it only updates when I refresh the page, not automatically. Shouldn't the ng-show's get updated automatically when the value of the Status field of the object gets changed?
<table>
<tr ng-repeat="object in current">
<td>Name: {{object.Name}} <br /> Status: {{object.StatusMessage}}<br /> ID: {{object.ID}} <br /> User: {{object.UserName}}</td>
<td>
<div ng-show="object.Status == 2 || object.Status == 3">
<img ng-src="{{getScreenshot(object.Name)}}" style="width: 500px; height: 300px">
</div>
<div ng-show="object.Status < 2 || object.Status > 3" style="font-size: large; font-weight: bold">
Screenshot not available.
</div>
</td>
</tr>
</table>
You can apply AngularJS $digest() function.
For more information about $digest() function go to AngularJS $watch() , $digest() and $apply()
You need to modify your controller code to something like this:
var app = angular.module('test', []);
app.controller('TestCtrl', function ($scope) {
$scope.testValue = 0;
setInterval(function() {
console.log($scope.testValue++);
$scope.$apply()
}, 500);
});
Jsfiddle: Link

How do I get rows from a list(table) in a protractor e2e test?

The list in question is a table generated by a reactive angular form which does not have a specific ID. Following code is used to generate the list in angular part:
<p-table id='paragraphList' *ngIf="paragraphsObs | async; else loading"
[value]="paragraphsObs | async"
selectionMode="single" (onRowSelect)="select($event)"
scrollable="true">
<ng-template pTemplate="header">
<tr> ...header... </tr>
</ng-template>
<ng-template pTemplate="body" let-paragraph let-rowData>
<tr [pSelectableRow]="rowData">
<td width="15%">{{paragraph.cell1}}</td>
<td width="10%">{{paragraph.cell2}}</td>
<td width="31%">{{paragraph.cell3}}</td>
<td width="11%">{{paragraph.cell4 | dateTransform: helperService.MM_DD_YYYY_HH_MM_A_Z_DATE_PATTERN}}
</td>
<td width="11%">{{paragraph.cell5}}</td>
<td width="11%">{{paragraph.cell6 | dateTransform: helperService.MM_DD_YYYY_HH_MM_A_Z_DATE_PATTERN}}
</td>
<td width="11%">{{paragraph.cell7}}</td>
</tr>
</ng-template>
</p-table>
The corresponding table generated at the front-end has the following html source:
<p-table _ngcontent-c6="" id="paragraphList" scrollable="true" selectionmode="single" ng-reflect-selection-mode="single" ng-reflect-scrollable="true" class="ng-star-inserted" ng-reflect-value="[object Object],[object Object">
<div class="ui-table ui-widget ui-table-hoverable-rows" ng-reflect-ng-class="[object Object]">
<div class="ui-table-scrollable-wrapper ng-star-inserted">
<div class="ui-table-scrollable-view" ng-reflect-frozen="false">
<div class="ui-table-scrollable-header ui-widget-header">...header...</div>
<div class="ui-table-scrollable-body">
<table class="ui-table-scrollable-body-table" ng-reflect-klass="ui-table-scrollable-body-table" ng-reflect-ng-class="[object Object]">
<tbody class="ui-table-tbody" ng-reflect-template="[object Object]">
<tr _ngcontent-c6="" ng-reflect-data="[object Object]" class="ng-star-inserted">...</tr>
<tr _ngcontent-c6="" ng-reflect-data="[object Object]" class="ng-star-inserted">...</tr>
...
</tbody>
</table>
<div class="ui-table-virtual-scroller"></div>
</div>
</div>
</div>
</div>
</p-table>
I want to reach to those inner elements and get them as a list. I have tried using class names with element and all locators, to get the elements but to no avail. Then I tried using tag names to reach to those elements but that too doesn't seem to work.
This following small snippet returns 0 for the count of elements that I try to obtain from the list.
element(by.id('paragraphList')).element(by.css('.ui-table-scrollable-body-table'))
.all(by.tagName('tr')).count().then(function (result) {
console.log(result);
});
Any help would be appreciated. Thanks
Considering above is your full rendered HTML..
The code below will give an Array of arrays, where each array would be containing texts from all the cells of a row.
Explanation:
The code has three functions,
populateData() - is the driving function where we pass the resolved list of rows.
Then _populateRows() and _populateCells() run recursively to gather the text from the cells. This is also possible to do with a loop (as protractor queues the promises by itself) but I like keeping things clear on my end. _populateRows() recur on rows and _populateCells() recur on cells of each row. (more in comments)
Note This first thing which you should do before implementing this is: check the count() (or .length of resolvedRows) of element.all(by.css('#paragraphList table tbody tr')). As basically this was your original question I believe. Now If you have a count, then you can go with this solution or whatever suites your need.
let allRows = element.all(by.css(`#paragraphList table tbody tr`)); //will have all the rows.
allRows.then((rowsResolved) => {
// now have all the rows
PO.populateData(rowsResolved).then((allData) => {console.log(allData)}) // should be an Array od arrays, each array would be containing texts from all the cells.
// Considering you have a Page Object and added the functions below in the Page Object.
// Page Object is nothing but another class where we keep our utility methods
})
// driving function
populateData(rowsResolved) {
let data = [];
return this._populateRows(0, rowsResolved, data);
}
// calls itself recursively to loop over the rows
private _populateRows(index, rowsResolved, data) {
if (index >= rowsResolved.length) {
let defer = protractor.promise.defer();
defer.fulfill(data);
return defer.promise; // so that it is chainable even if I don't have any rows
}
let cells = element.all(by.css(`#paragraphList table tbody tr:nth-child(${index + 1}) td`));
cells.then((cellsResolved) => {
let cellData = [];
if (cellsResolved.length) {
data.push(cellData);
}
this._populateCells(0, cellsResolved, cellData);
return this._populateRows(index + 1, rowsResolved, data);
})
}
// calls itself recursively to loop over all the cells ofeach row.
private _populateCells(index, cellsResolved, cellData) {
if (index >= cellsResolved.length) {
let defer = protractor.promise.defer();
defer.fulfill(cellData);
return defer.promise; // so that it is chainable even if I don't have any cells(that would be an incorrect structure though, if a row exists then cells have to exist )
}
cellsResolved[index].getText().then((cellValue) => {
cellData.push(cellValue)
});
return this._populateCells(index + 1, cellsResolved, cellData);
}

How to print data in html using ng-repeat angularjs

I have json data in controller as response. I have to print that data in html.
for that I have done as below:
In my controller
.controller('DataImportControl', ['$scope','$http', '$location', '$rootScope' , function($scope, $http, $location, $rootScope) {
console.log(" In dataimportCtrl");
$scope.readCustomer = function(){
console.log("in read customer");
$http.post('/custimport').success(function(response) {
console.log("in controller");
console.log("controller:"+response);
$scope.data=response;
}).error(function(response) {
console.error("error in posting");
});
};
}])
My html code:
<html>
<head>
<script src = "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
</head>
<body>
<div ng-app="" ng-controller="DataImportControl">
<form ng-submit="readCustomer()">
<button type="submit" >Submit</button>
</form>
<table class="table">
<thead>
<tr>
<th>Code exists in customer master</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="cust in data ">
<td>{{cust.customer_code}}</td>
</tr>
</tbody>
</table>
</div>
<div >
</div>
</body>
</html>
My json data as response in controller :
{"jarray":[{"customer_name":["Ankita"],"customer_code":["c501"]}]}
My question is how to print json data in html using ng-repeat in my case?
Thanks in advance...
I'm assuming you want to print out the actual object, in that case just do
{{cust | json}}
Wrap it in pre tags to have it prettified.
The data being returned from your service is strangely formatted. I would assume you have multiple records being returned, but you are only showing one in this example.
The record you are showing here is an object, with an array as one of the properties. It is not clear if your object has multiple arrays, or if this array has multiple customer objects embedded in it. However, I worked up a quick plunker showing how to iterate through in both situations.
first, if you intend to iterate through data directly, and data will hold multiple arrays, you would use the (key, value) syntax, since data itself is an object and not an array.
<div ng-repeat="(key, value) in data">
key: {{key}}
<br/>value: {{value}}
<div ng-repeat="customer in value">
Customer name: {{customer.customer_name}}
<br/>Customer code: {{customer.customer_code}}
</div>
</div>
However, if your data is only returning a single object property, jarray, and you will always be iterating through this same property, the outer ng-repeat is unnecessary:
<div ng-repeat="customer in data.jarray">
Customer name: {{customer.customer_name}}
<br/>Customer code: {{customer.customer_code}}
</div>
you may want to clean up your service, either in angular or on your server, and remove jarray all together, if it doesn't hold a specific significance to the data.
http://plnkr.co/edit/Nq5Bo18Pdj4yLQ13hnrJ?p=preview

ng-repeat with json data

I have the following json data saved in json column in postgres database
{
"runway": [
{"number":"13R/13L", "length":"14511", "lengthuom":"ft"},
{"number":"10R/15L", "length":"98641", "lengthuom":"ft"},
{"number":"16R/22L", "length":"65410", "lengthuom":"ft"}
]
}
I'm tryig to get it by ng-repeat but I don't know how.
I try with the following code
<tr ng-repeat="ass in assetb track by $index">
<td>{{ass.runway.number}}</td>
</tr>
Can anyone help me please to display this data in table?
Check out this may help you :--
function MyController($scope){
var data = {"runway":[ {"number":"13R/13L", "length":"14511", "lengthuom":"ft"},
{"number":"10R/15L", "length":"98641", "lengthuom":"ft"},
{"number":"16R/22L", "length":"65410", "lengthuom":"ft"} ]}
$scope.list = data.runway;
}
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
</head>
<body>
<div ng-controller="MyController">
<p ng-repeat="l in list track by $index">{{l.number}}</p>
</div>
</body>
</html>
Remove the line track by $index and use like
<tr ng-repeat="ass in assetb.runway">
<td>{{ass.number}}</td>
</tr>
Fiddle
Get your data from database and store it in $scope variable. Something like:
$scope.assetb = {
"runway": [
{"number":"13R/13L", "length":"14511", "lengthuom":"ft"},
{"number":"10R/15L", "length":"98641", "lengthuom":"ft"},
{"number":"16R/22L", "length":"65410", "lengthuom":"ft"}
]
};
And since ng-repeat requires an array, modify your HTML something like this:
<tr ng-repeat="ass in assetb.runway track by $index">
<td>{{ass.number}}</td>
</tr>

Angular.js Infinite Loop of calling functions

My problem is in the following template :
<div class="container">
<h1>Process Definitions</h1>
<table class="table table-stripped" >
<tr>
<td><strong>Name</strong></td>
<td><strong>Id</strong></td>
<td><strong>Version</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="def in defs | filter: global.search">
<td>{{def.name}}</td>
<td>{{def.id}}</td>
<td>{{def.version}}</td>
<td><button type="button" class="btn btn-warning" ng-click="redirectToInstance(def.id)">Instances</td>
<!--<td><h4><small>{{'Current :' + getCount(def.id) }}</small></h4></td>-->
<td><button type="button" class="btn btn-warning" ng-click="redirectToTasks(def.id)">Tasks</td>
</tr>
</table>
</div>
The problem is the function call inside the expression inside the comment-tag.
the function called is in this controller :
BPMNControllers.controller('ProcessDefinitionCtrl', ['$scope','$location', 'ProcessDefinitions','ProcessInstances',
function($scope,$location, ProcessDefinitions,ProcessInstances) {
$scope.defs = ProcessDefinitions.query();
$scope.redirectToInstance = function(id){$location.path('/process-definitions/' + id);};
$scope.redirectToTasks = function(id){$location.path('/tasks/def'+id)};
$scope.getCount = function (id){
var countObj = ProcessInstances.getCount({processDefinitionId : id});
return countObj.count;
};
console.log('ProcessDefinitionCtrl');
}]);
And the following service is important, cause it's querying a rest-api.
BPMNServices.factory('ProcessInstances', ['$resource','restUrl',
function($resource,restUrl){
var url = restUrl+'engine-rest/process-instance/:id'
return $resource(url,{id:'#id'},{
query : {method:'GET',isArray:true},
get : {method:'GET'},
getCount : {method:'GET',url:restUrl+'engine-rest/process-instance/count'}
},{})
}]);
This results in an infinite loop of ajax calls.I think i know that the problem is the asynchronous call, and since it's not directly bound the call is not fast enough and thus called and called again. How can i do this?
And the ProcessDefinitions as requested:
BPMNServices.factory('ProcessDefinitions', ['$resource','restUrl',
function($resource,restUrl){
var url = restUrl + 'engine-rest/process-definition/:id'
return $resource(url, {id : '#id'}, {
query: {method:'GET', isArray:true},
get : {method:'GET'},
start: {method:'POST',url:url+'/start'}
},{});
}]);
And the model for the global search filter :
<input type="text" class="form-control" placeholder="Search" ng-model="global.search">
The infinite loop is a result of your watched view expression calling a function which itself results in the triggering of a $digest cycle.
A good explanation, and another example, is provided in Infinite loop with Angular expression binding
As for your particular code, you could use a directive in place of the view expression:
HTML
<!-- results in infinite digest Count: {{getCount(def.id)}} -->
Count: <count></count>
JS
.directive('count', function(ProcessInstances){
return {
restrict: 'E',
replace: true,
link: function(scope) {
scope.countRes = ProcessInstances.getCount(scope.def.id);
},
template: '<span>{{countRes.count}}</span>'
}
});
Demo