How can I create a custom command to fill fields in both scenarios with different structures? - css-selectors

So I have 2 scenarios, from different pages on the application I'm testing:
Scenario 1:
<tbody>
<tr>
<td class="colLabel90 colCampo">
<label style="font-weight: bold">* Nome:</label>
</td>
<td>
<input type="text" class="ui-inputfield ui-inputtext ui-widget ui-state-default ui-corner-all requiredColor role="textbox" aria-disabled="false" aria-readonly="false">
</td>
</tr>
<tr>
.....
</tr>
</tbody>
Scenario 2:
<tr role="row">
<th id="dataTableFormId:DataTableId:j_idt169" class="ui-state-default ui-sortable-column ui-filter-column ui-resizable-column colFilterSize" role="columnheader" aria-label="Nome: activate to sort column ascending" scope="col" style="width:90%" aria-sort="other">
<span class="ui-column-resizer ui-draggable ui-draggable-handle"> </span>
<span class="ui-column-title">Name</span>
<span class="ui-sortable-column-icon ui-icon ui-icon-carat-2-n-s"> </span>
<input id="dataTableFormId:DataTableId:j_idt169:filter" name="dataTableFormId:DataTableId:j_idt169:filter" class="ui-column-filter ui-inputfield ui-inputtext ui-widget ui-state-default ui-corner-all" autocomplete="off" role="textbox" aria-disabled="false" aria-readonly="false">
</th>
<th id="dataTableFormId:DataTableId:j_idt171" class="ui-state-default ui-sortable-column ui-filter-column ui-resizable-column colFilterSize" role="columnheader" aria-label="Fabricante: activate to sort column ascending" scope="col" style="width:90%">
<span class="ui-column-resizer ui-draggable ui-draggable-handle" style="display: none;"> </span>
<span class="ui-column-title">Manufacturer</span>
<span class="ui-sortable-column-icon ui-icon ui-icon-carat-2-n-s"></span>
<input id="dataTableFormId:DataTableId:j_idt171:filter" name="dataTableFormId:DataTableId:j_idt171:filter" class="ui-column-filter ui-inputfield ui-inputtext ui-widget ui-state-default ui-corner-all" autocomplete="off" role="textbox" aria-disabled="false" aria-readonly="false">
</th>
</tr>
Here is what I'm trying to do on Cypress:
Cypress.Commands.add("typeOnFields", (field, value) => {
cy.get('#center').contains(field).parent().find('input').clear().type(value)
})
//Where field is the name of the field in <label> or <span>, in this case it's 'Name'
This is not working, find() won't find the input in any scenario.

Because the two scenarios have different structures and parent elements, you would need to use a variant of .parents() that keeps moving up to the first parent that contains an input
cy.contains(field) // return the <label> or <span> with "field"
.parents(':has(input)') // move up until element has an <input> inside
.eq(0) // take first (multiple are returned)
.find('input') // find the <input> element
.clear().type(value)
To avoid complexity, I would actually use two commands here one for the table header and one for the table body.

Related

PrimeNG v5.2.4 p-table global filter not working

I used p-datatable previously and the global filter worked. However when I changed to p-table, the global filter template displayed nicely but the input box is not clickable.
Here's the code
<p-table #dt
[value]="sensorLocationList"
[columns]="cols"
[(selection)]="selectedSl"
sortMode="multiple" [paginator]="true"
[rows]="20"
[globalFilterFields]="['dummy1','dummy2','dummy3','dummy4']"
>
<ng-template pTemplate="caption">
<div style="text-align: left">
<i class="fa fa-search" style="margin:4px 4px 0 0"></i>
<input type="text" pInputText size="50" placeholder="Global Filter" (input)="dt.filterGlobal($event.target.value, 'contains')" style="width:auto">
</div>
</ng-template>
Header:
<ng-template pTemplate="header" let-columns>
<tr>
<th style="width: 2.25em"></th>
<th *ngFor="let col of columns" [pSortableColumn]="col.field">
{{col.header}}
<p-sortIcon [field]="col.field"></p-sortIcon>
</th>
</tr>
<tr>
<th style="width: 2.25em">
<p-tableHeaderCheckbox></p-tableHeaderCheckbox>
</th>
<th *ngFor="let col of columns" [ngSwitch]="col.field">
<input *ngSwitchCase="'dummy1'" pInputText placeholder="Search" type="text" class="search-box" (input)="dt.filter($event.target.value, col.field, col.contains)">
<input *ngSwitchCase="'dummy2'" pInputText placeholder="Search" type="text" class="search-box" (input)="dt.filter($event.target.value, col.field, col.contains)">
<input *ngSwitchCase="'dummy3'" pInputText placeholder="Search" type="text" class="search-box" (input)="dt.filter($event.target.value, col.field, col.contains)">
<input *ngSwitchCase="'dummy4'" pInputText placeholder="Search" type="text" class="search-box" (input)="dt.filter($event.target.value, col.field, col.contains)">
</th>
</ng-template>
And one sample of body:
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr [pSelectableRow]="rowData">
<td [pEditableColumn]="rowData" [pEditableColumnField]="'dummy1'" [ngStyle]="cellEdit(rowData)">
<p-cellEditor>
<ng-template pTemplate="input">
<input pInputText type="text" [(ngModel)]="rowData.dummy1">
</ng-template>
<ng-template pTemplate="output">
{{rowData.dummy1}}
</ng-template>
</p-cellEditor>
</td>
</tr>
</ng-template>
</p-table>
Everything works fine including the column filter. I've searched everywhere for the solution and found most of the problem is because the PrimeNG version was not up-to-date, but my version is updated. Any idea?
Add [pSortableColumnDisabled]="!col.sortable" to the table header tag:
<th *ngFor="let col of columns" [pSortableColumn]="col.field" [pSortableColumnDisabled]="!col.sortable">
Remove "ng-template" from around the GlobalFilter

Display Data On Modal Screen Based On User Selection Using Check Box

"I've displayed 20 records in navigation tab and against each records I've added coloumn for checkbox. My requirement is if user selects records (row) 1, 4, 8 using checkbox and click on "Edit" button on top of Navigation tab then it should display on Modal screen so that user can edit it.
if he/she selects records 5, 8, 6 then records should be display in that particular order.
I google it but couldn't find any related posts.
Below is my HTML code:
<div ng-app="RecordApp" ng-controller="recordcontroller" class="container-fluid">
<div class="input-group">
<ul class="nav nav-tabs">
<li role="menu" class="active"><a href="#" data-toggle="tab" >User Data</a></li>
</ul>
<table class="table">
<thead>
<tr>
<th>
Select
</th>
<th>
Test1
</th>
<th>
Test2
</th>
<th>
Test3
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in Records | orderBy:SortBy:Reverse ">
<td>
<input type="checkbox" checked="checked" ng-model="record.Selected" ng-change="Checked(record)" />
</td>
<td>{{ record.Test1 }}</td>
<td>{{ record.Test2 }}</td>
<td>{{ record.Test3 }}</td>
</tr>
</tbody>
</table>
</div>
following is my AngularJs code for populating the navigation tab
$http.get(pageBaseUrl + "api/records").success(function (records) {
$scope.Records = records;
$scope.IsLoading = false;
});
Below is the code of Button and Modal screen:
<div class="input-group">
<button type="button" data-target="#editRecords" data-toggle="modal" class="btn btn-primary navbar-btn">
<span class="glyphicon glyphicon-floppy-disk"></span>
Edit Multiple Records
</button>
</div>
<div id="editRecords" class="modal" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h2>Edit Data For Selected Records </h2>
</div>
<div class="modal-body">
<table class="table-condensed table-striped">
<thead>
<tr>
<th>Test 1</th>
<th>Test 2</th>
<th>Test 3</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in Records | orderBy:SortBy:Reverse">
<td><input type="text" class="form-control input-sm" /></td>
<td><input type="text" class="form-control input-sm" /></td>
<td><input type="text" class="form-control input-sm" /></td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="SaveRecords();">Save Records</button>
<button type="button" class="btn btn-default" data-dismiss="modal" ng-click="UnmarkForEdition()">
Cancel
</button>
</div>
</div>
</div>
</div>
Thanks for the code, here is my solution,
JSFiddle Demo
Issues:
First I check if the object contains any selected checkboxes using the code.
$scope.checkCheckbox = function(){
return $filter('filter')($scope.Records, {Selected: true}).length === 0;
}
In the above code, I check the ng-repeat array if there is any object containing the property Selected:true, if there are none, then the length will be zero which using a comparator operator, I return a boolean. This is used by the HTML element button attribute ng-disabled and disables the input.
<button type="button" ng-disabled="checkCheckbox()" data-target="#editRecords" data-toggle="modal" class="btn btn-primary navbar-btn">
<span class="glyphicon glyphicon-floppy-disk"></span>
Edit Multiple Records
</button>
When the edit multiple records, button is clicked, I open the modal, and in the code I have added a simpleng-if` which will show only the inputs where the checkbox is selected!
<tr ng-if="record.Selected" ng-repeat="record in Records | orderBy:SortBy:Reverse">
<td><input type="text" class="form-control input-sm" /></td>
<td><input type="text" class="form-control input-sm" /></td>
<td><input type="text" class="form-control input-sm" /></td>
</tr>
Let me know if this fixes the issue.

Display table rows in angularjs, if data exists

I want to have a table consisting of 3 columns, the code looks like this
<table class="table-striped table-bordered table-condensed">
<tbody>
<tr ng-if="$index%3==0" ng-repeat="permission in vm.parent.getAllPermissions(category)">
<td ng-repeat="i in [0,1,2]" class="col-xs-2">
<span>
<input type="checkbox" checklist-model="vm.data.permissions" checklist-value="vm.parent.getPermission(category,$parent.$index+i)"> {{vm.parent.getPermissionTitle(category,$parent.$index+i) || " "}}
</span>
</td>
</tr>
</tbody>
</table>
That works great except for a small issue.
There's simply not enough json data to fill 3 rows, so 2 checkboxes are displayed empty
What I tried, is writing something like
vm.hasPermission = function(category, index) {
var permissions = vm.getAllPermissions(category);
return permissions && index < permissions.length
};
And then something like
<span>
<input ng-if="vm.parent.hasPermission(category,$parent.$index+i)"type="checkbox"
checklist-model="vm.data.permissions" checklist-
value="vm.parent.getPermission(category,$parent.$index+i)"> {{vm.parent.getPermissionTitle(category,$parent.$index+i) || " "}}
</span>
It fixes the problem but not on all tables, some tables would still have empty checkboxes.
I get the permission titles like this
vm.getPermissionTitle = function(category, index) {
var permissions = vm.getAllPermissions(category);
if (index < permissions.length) {
return i18n.get(permissions[index]);
} else {
return '';
}
};
I tried removing the return, didn't fix it.
change:
<td ng-repeat="i in [0,1,2]" class="col-xs-2">
<span>
<input type="checkbox" checklist-model="vm.data.permissions" checklist-value="vm.parent.getPermission(category,$parent.$index+i)"> {{vm.parent.getPermissionTitle(category,$parent.$index+i) || " "}}
</span>
</td>
for:
<td ng-repeat="i in [0,1,2]" class="col-xs-2">
<span ng-if="vm.parent.getPermissionTitle(category,$parent.$index+i)!=''">
<input type="checkbox" checklist-model="vm.data.permissions" checklist-value="vm.parent.getPermission(category,$parent.$index+i)"> {{vm.parent.getPermissionTitle(category,$parent.$index+i)}}
</span>
</td>
if I understood well your code and your problem, vm.parent.getPermission(category,$parent.$index+i) returns the text (permission) so just check that is not empty... it may also work like:
<td ng-repeat="i in [0,1,2]" class="col-xs-2">
<span ng-if="vm.parent.getPermissionTitle(category,$parent.$index+i)">
<input type="checkbox" checklist-model="vm.data.permissions" checklist-value="vm.parent.getPermission(category,$parent.$index+i)"> {{vm.parent.getPermissionTitle(category,$parent.$index+i)}}
</span>
</td>
because vm.parent.getPermission(category,$parent.$index+i) returning nothing could evaluate false.
I haven't try it.
The solution is
<table class="table-striped table-bordered table-condensed">
<tbody>
<tr ng-if="$index%3==0" ng-repeat="permission in vm.parent.getAllPermissions(category)">
<td ng-repeat="i in [0,1,2]" class="col-xs-2">
<span ng-if="vm.parent.getPermission(category,$parent.$index+i)">
<input type="checkbox" checklist-model="vm.data.permissions" checklist- value="vm.parent.getPermission(category,$parent.$parent.$index+i)">
{{vm.parent.getPermissionTitle(category,$parent.$parent.$index+i)}}
</span>
</td>
</tr>
</tbody>
</table>
So basically {{vm.parent.getPermissionTitle(category,$parent.$parent.$index+i)}}

Keep dynamic table synced with model in AngularJS

I have the following sample model:
{
a:{
x:0,
z:0,
f:1
},
b:{
x:"a",
u:"b"
}
}
Which I render into two different tables
<div class="col-sm-5">
<h1>A</h1>
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr ng-repeat="(key,value) in schema.a">
<td>
<input type="text" ng-model="key" required>
</td>
<td>
<input type="text" ng-model="value" required>
</td>
<td></td>
</tr>
</table>
</div>
<div class="col-sm-5 col-md-offset-2">
<h1>B</h1>
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr ng-repeat="(key,value) in schema.b">
<td>
<input type="text" ng-model="key" required>
</td>
<td>
<input type="text" ng-model="value" required>
</td>
<td></td>
</tr>
</table>
</div>
The tables are dynamic, which means I can add new rows to it.
Now when I change any values inside the table, they aren´t synchronized with the model -> Editing not possible
What do I need to do to store changes automatically in the original
model?
If this is not possible, how can I get a Json Schema from my table
like the one the tables are rendered from, so that I only have to
overwrite the old one?
First off you can't dynamically change an object property name or key. So what you are trying to do with ng-model="key" simply won't work.
As far as the value part you should be using the object reference in your ng-model
<tr ng-repeat="(key,value) in schema.b">
<td>{{key}}</td>
<td>
<input type="text" ng-model="schema.b[key]" required>
</td>
<td></td>
</tr>
if you need to be able to edit the key then you need to change your data structure to an array of objects with each object having the same property names for keys

Error in selecting many checkboxes in AngularJS

I have created a table from 2 different arrays in AngularJS that contain employees name and services and rest of the cells contain Checkboxes now I want get the ID's of selected Checkboxes that I have created another array in the controller,
but the view allows me to select only one Checkbox from many in the row
here is my Html
<form ng-submit="save()">
<table border="1">
<tr>
<td><strong>Services</strong></td>
<td ng-repeat="e in PBA">{{e.Name}}</td>
</td>
<tr ng-repeat="(index,i) in SOB">
<td>{{i.Name}}</td>
<td ng-repeat="e in PBA track by $index">
<input type="checkbox" name="cb" ng-true-value="{{e.Id}}_{{i.Id}}" ng-model="ids[index]" />
</td>
</tr>
</table>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" />
</div>
</form>

Resources