Getting value from ng-repeat in protractor test case - angularjs

I want to add two counts in the protractor testcase from ng-repeat .But I am unable to fetch the count object via repeater.
html:
<div ng-repeat="act in actives">
<div>
<input id="checkbox-active" ng-model="act.checked"
ng-change="chooseActive(actInact)"/> {{actInact.name}}
</div>
<div><span id="active-count">{{actInact.count}}</span></div>
</div>
test.spec
this.getStateCount = function () {
var item = element.all(by.repeater('activeInactive in activeInactives'));
console.log("item"+item[0].count);
console.log("item"+item[0]);
item.getText().then(function(text){
console.log("text1+txt2"+text[0]+text[1]);
})
};
gives active 1 inactive 2 in console.
when I tried
console.log("item"+item[0].count); gives undefined
and exception is thrown.
and item is coming as object object.

Related

How to get the element with the testid using react testing library?

Hi i want to access the first div with class "icon" using getByTestId.
below is how the DOM looks,
<div class="parent">
<div data-testid="add">
<div class="info"></div>
<div class="action">
<div class="icon"/> //want to access this
</div>
</div>
</div>
<div class="parent">
<div data-testid="add">
<div class="info"></div>
<div class="action">
<div class="icon"/>
</div>
</div>
</div>
As you see from above there are multiple elements with testid "add" how can i get the first add div and access its child div with class icon.
i have tried
const element = queryAllByTestId('add')[0].querySelector(
'div'
)[1];
this gives element undefined.
could someone help me with this. thanks.
getAllBy
getAllBy* queries return an array of all matching nodes for a query,
and throw an error if no elements match.
queryAllBy
queryAllBy* queries return an array of all matching nodes for a
query, and return an empty array ([]) if no elements match.
Query Cheetsheet
Use the query variant so as not to throw in a test if no matches found, and use querySelectorAll since querySelector returns only the first element that matches, or null.
const element = queryAllByTestId("add");
if (element.length) {
let divs = element[0].querySelectorAll("div");
// ...get the div node you need
}
You can even specify divs with a specific class
const element = queryAllByTestId("add");
if (element.length) {
let divs = element[0].querySelectorAll("div.icon");
// ...get the div node you need
}

view is not being updated after updating object from server call angular 4

I have declare a Array of object in angular 4 like this
public onlinUsers;
I Used this like here
<div class="row" >
<h2>Online users</h2>
{{onlinUsers}}
<div *ngFor="let i of onlinUsers">
<a (click)="openPrivate(i.name)">{{i.name}}</a>
</div>
</div>
and updating it here like this
ngOnInit() {
this.socket.on('onlineUsers',function(data){
this.onlinUsers=data.data
console.log( this.onlinUsers)
})
}
console.log working fine
Why my html is not being rendered . please help
this.socket.on('onlineUsers',function(data){
should be
this.socket.on('onlineUsers', (data) => {
otherwise this won't work as you expect inside the function.
Search for arrow functions for more details.

Angular Scope Variables not being Updated

I'm fairly new to Angular, but it seems this should work:
HTML:
<div style="float:left;width:26%;height:96%;margin:2% 0 2% 0;background-color:#efefef;padding:0 2% 0 2%;" ng-app="fcApp"
ng-controller="fcCtrl">
<span>Find:</span>
<input id="student_search" type=text
ng-keypress="selectFirstStudent($event)"
ng-model="student_search" placeholder="name / ssn">
<div style="max-height:90%;" ng-show="student_search">
<div style="width:100%;height:30px;"
ng-repeat="student in students | filter:student_search as filtered"
ng-click="newStudent(student);">
{{ student.firstname }} {{ student.lastname }} - {{ student.ssn }}
</div>
</div>
<div style="float:left;width:70%;">
<input id="ssn" ng-model="student.ssn">
{{ student.ssn }}
</div>
Controller(partial):
$scope.getStudents = function(){
$http.get('/getstudents/')
.then(function(response){
$scope.students = response.data.students;
$scope.student = $scope.students[0];
}
);
};
$scope.getStudents();
So the getStudents function is obviously working to the extent it actually gets a list of the students from the database. But all of my $scope variables aren't being updated.
As I type part of a name in the input box, the list of students gets properly filtered down, and the list gets shorter. However, I see no values in the list, only the "-" which should appear between last name and SSN. That appears on every row of the filtered result.
Didn't supply all code, but when I click on one of the items in the filtered list, I get an alert showing selected student ID and SSN. So the data is there, it's just not appearing in the Angular variables. Also, last div should be showing the student SSN twice, right? Nothing there either. BTW, clicking the filtered list does fire event which sets $scope.student to the student object clicked, as my alert demonstrates.
So why don't I see any of the values, either in the filtered list or the input with ng-model set?
You are using
$scope.student = $scope.students[0];
inside your method.
And also
ng-repeat="student in students | filter:student_search as filtered"
Both are same variable so your DOM is not updated.
Try using a different name as below, for example I am using stud
<div style="max-height:90%;" ng-show="student_search">
<div style="width:100%;height:30px;"
ng-repeat="stud in students | filter:student_search as filtered"
ng-click="newStudent(stud);">
{{ stud.firstname }} {{ stud.lastname }} - {{ stud.ssn }}
</div>
</div>

access an element inside ng-repeat when dynamic html loaded

I am trying to access an DOM element inside a dymanic loaded HTML with http get request. The code that I am using inside controller is
$http.get("/ProjectManager/Edit?id=" + requestId).success(function (data, status, headers, config) {
data = data.trim();
var newDirective = angular.element(data);
angular.element(document.getElementById("editDiv")).html(newDirective);
$compile(newDirective)($scope);
var resources = angular.element(document.getElementById("projectResources")).val();
for (var i = 0; i < resources.length; i++) {
var resourceData = new ProjectResourcesModel(resources[i].ResourceID, resources[i].ProjectResourceID, resources[i].Employee, resources[i].IsApprover, resources[i].StartDate,
resources[i].EndDate)
$scope.resource.push(resourceData);
//$scope.$apply();
var id = "startDate" + resources[i].ResourceID;
angular.element(document.getElementById(id)).datetimepicker({
defaultDate: resources[i].StartDate,
format: 'MM/DD/YYYY',
})
}
})
I am trying to access a element with particular id that is present in my array element.
View HTML inside a ng-repeat is as follows
<div>
<div class="form-group">
<div class='input-group date' id='startDate{{item.ResourceID}}'>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
<input ng-model="item.StartDate" type='text' id="txtStartDate{{item.ResourceID}}" class="form-control" />
</div>
</div>
</div>
</div>
I have to attach bootstrap datetimepicker to a textbox so I want to access a div inside ng-repeat whose ID is present inside by ng-repeat array.
But when I access the item with that id inside success of get request I am not getting the element. for e.g id of div would be startDate151 after the view binding.
So I tried using $scope.$apply() with which I am able attach the datepicker to element inside ng-repeat but I started getting a console error
Error: [$rootScope:inprog] $digest already in progress
Can anyone help me to resolve this or can I use some other alternative in this situation.

duplicates in a repeater are not allowed angular

I'm trying to create a form like below, this using ng-repeat directive in angular and it whenever I created a new row complains
"Duplicates in a repeater are not allowed.".
While I understand the solution for this is by putting "track by $index", however it causes another issue, which clicking delete on one row deletes the value of other field. So I suspect that track by index is OK for static text but not input form. So how to use ng-repeat correctly for my case?
My jsfiddle : demo.
Edit : I do aware that json array of object will solve my issue ( because for object angular create $$hashKey ) and already implemented this for most of my other module. But I am actually expecting some fix that can be done without really change my json array of string. Sorry for not being clear.
My current code :
HTML
<div class="row-fluid spacer10">
<a ng-click="addAKA()" class="btn btn-primary spacer5 left30"><i class="icon-plus icon-white"></i> Add New Alias</a>
</div>
<div class="row-fluid spacer10"></div>
<div class="row-fluid spacer5" ng-repeat="item in aliasList track by $index">
<input type="text" class="span6 left30" ng-model="item">
<button class="btn btn-danger" ng-click="deleteAKA($index)">delete</button>
<BR/>
</div>
Javascript
$scope.addAKA = function ()
{
if($scope.aliasList == null)
{
$scope.aliasList = [];
}
$scope.aliasList.push("");
$scope.aliasjson = JSON.stringify($scope.aliasList);
}
$scope.deleteAKA = function (idx)
{
var aka_to_delete = $scope.aliasList[idx];
$scope.aliasList.splice(idx, 1);
$scope.aliasjson = JSON.stringify($scope.aliasList);
}
I would guess this is caused when there are more than one empty strings in the list.
If this is the case, it is caused because any two empty strings are equals in JS and Angular repeater does not allow duplicate values (as clearly stated in the message). This is a valid decision as they have to relate an object in the list with its DOM tree to minimize DOM manipulation.
A solution would be to insert simple objects containing the string in the model:
$scope.addAKA = function () {
...
$scope.aliasList.push({value:""});
...
};
And adjust your template:
<input type="text" class="span6 left30" ng-model="item.value">
Since all new objects are different, your problem should be solved.
See a fiddle where a filter is implemented to transform the model back to a list of strings.
When you type in a new created input, your list stays the same. Angular on any list change will update the view (ng-repeat) and remove all new stored text. Therefore we need to add ng-change to update our list on any input change
Add ng-change="change(i, $index) to your item and it should work
HTML
<div ng-controller='ctrl'>
<ol>
<li ng-repeat='i in list track by $index'>
<input type='text' ng-model='i' ng-change="change(i, $index)"></input>
<button ng-click='deleteItem($index)'>Delete</button>
</li>
</ol>
<button ng-click='addItem()'>Add</button>
<div>ITEM: {{list | json}}</div>
</div>
Javascript
angular.module("app", []).controller("ctrl", function ($scope) {
$scope.list = ["one","two"];
$scope.addItem = function ()
{
$scope.list.push("");
};
$scope.deleteItem = function (idx)
{
var item_to_delete = $scope.list[idx];
$scope.list.splice(idx, 1);
};
$scope.change = function (item, idx)
{
$scope.list[idx] = item;
};
});
See fixed Demo in DEMO
Yes, pushing more than one empty string will result in ng-repeat complaining.
In addition, you can also try:
if ($scope.aliasList.indexOf(VALUE_TO_ADD) === -1) {
...
}

Resources