How to check if class doesn't exist in element - puppeteer

I have the following code:
<div class="ProductSize-group">
<div class="c-form-field c-form-field--radio c-form-field--disabled c-form-field--unavailable ProductSize"><label for="input_radio_size_060" aria-hidden="true" class=""><span class="c-form-label-content">06.0</span></label><input name="size" aria-label="Size 06.0, out of stock" id="input_radio_size_060" type="radio" disabled="" required="" value="06.0"></div>
<div class="c-form-field c-form-field--radio c-form-field--disabled c-form-field--unavailable ProductSize"><label for="input_radio_size_065" aria-hidden="true" class=""><span class="c-form-label-content">06.5</span></label><input name="size" aria-label="Size 06.5, out of stock" id="input_radio_size_065" type="radio" disabled="" required="" value="06.5"></div>
</div>
This is just part of it. I need to check if this div contains class
<div class="c-form-field c-form-field--radio c-form-field--disabled c-form-field--unavailable ProductSize">
Specifically check if this div contains class c-form-field--unavailable
This is what I have:
const productSizeOptions = await page.$(".ProductSize-group");
productSizeOptions.map(productSizeOption => {
})
But I can't figure out how to loop through each class to see if it exists in the element or not. Any ideas?

Just use :not
await page.$(".ProductSize-group:not(.c-form-field--unavailable)");

You can use Element.classList:
const foo = await page.$('.foo');
const hasBarClass = await page.evaluate(
element => element.classList.contains('bar'),
foo
);
if (!hasBarClass) console.log('Element.foo has no .bar class.');

Related

How to get html form to see textbox data in js

I have a form with 3 entries and an input submit button. One field is a textbox that prompt a numerical entry and the other 2 are selection fields. After many attempts I was finally able to get the browser to pick up on the selection options, however when i console.log it its still not seeing the numerical entry.
const submitForm = (event) => {
const form = document.getElementById('form');
const data = new FormData(form);
const dataObject = {};
for (const [key, value] of data.entries()) {
dataObject[key] = value;
};
console.log(dataObject);
return false;
}
<form name="form" onsubmit="javascript:submitForm();return false;" id="form">
<div class="dataEntry">
<div class="grossIncome">
<label for="grossIncomeEntry">Enter your gross income</label>
<input type="number" inputmode="numeric" id="incomeTextBox" placeholder="Gross Income" required>
</div>
<div class="timeframe">
<label for="perTimeframe">Per</label>
<select name="dateRange" id="incomeTimeframe">
<option value="Annual">Annual</option>
<option value="Monthly">Monthly</option
</select>
</div>
<div class="employmentLocation">
<label for="workingProvince">Where do you work?</label>
<select name="workingProvince" id="provinces">
<option value="Ontario">Ontario</option>
<option value="Quebec">Quebec</option>
</select>
</div>
<button type="submit" id="calculate">Calculate</button>
</div>
</div>
</form>
This operation:
new FormData(form)
Is essentially creating key/value pairs of form elements/values. The key is the name of the form element, and the value is its current value.
You can observe this when you see the property names in the resulting object being logged to the console. The property name for the <select> value is "dateRange". When you observe your code, where do you expect that property name comes from? Given that, what do you expect the property name for the <input> value to be and why?
Your <select> has a name, but your <input> does not. Simply add a name to it:
const submitForm = (event) => {
const form = document.getElementById('form');
const data = new FormData(form);
const dataObject = {};
for (const [key, value] of data.entries()) {
dataObject[key] = value;
};
console.log(dataObject);
return false;
}
<form name="form" onsubmit="javascript:submitForm();return false;" id="form">
<div class="dataEntry">
<div class="grossIncome">
<label for="grossIncomeEntry">Enter your gross income</label>
<input type="number" inputmode="numeric" id="incomeTextBox" placeholder="Gross Income" required name="incomeTextBox">
</div>
<div class="timeframe">
<label for="perTimeframe">Per</label>
<select name="dateRange" id="incomeTimeframe">
<option value="Annual">Annual</option>
<option value="Monthly">Monthly</option
</select>
</div>
<div class="employmentLocation">
<label for="workingProvince">Where do you work?</label>
<select name="workingProvince" id="provinces">
<option value="Ontario">Ontario</option>
<option value="Quebec">Quebec</option>
</select>
</div>
<button type="submit" id="calculate">Calculate</button>
</div>
</div>
</form>

Using form labels for multiple elements

My page has many js-generated form elements which can exist simultaneously but need to be created from the same block of code (jsx, react). My problem is that I need to give labels to all these form elements for semantics and seo, but I can't give them all the same id (becuase html ids are unique). Is the only option to dynamically generate unique html ids? Is there any way to do this with html classes?
My code would look something like this:
function cardEditor() {
return (
<form>
<label for="card-title">Title: </label>
<input type="text" id="card-title">
<button type="submit">Save</button>
</form>
);
}
You can pass id as props to your component
const Input = ({ id }) => {
return <>
<label for={id}>Title: </label>
<input type="text" id={id}>
</>
}
function cardEditor() {
return (
<form>
<Input id="card-title-1" />
<Input id="card-title-2" />
<Input id="card-title-3" />
<button type="submit">Save</button>
</form>
);
}
or generate unique ids for your form elements
const uuid = () => Math.random().toString(36).slice(-6);
const Input = () => {
const id = uuid();
return <>
<label for={id}>Title: </label>
<input type="text" id={id}>
</>
}
function cardEditor() {
return (
<form>
<Input/>
<Input/>
<Input/>
<button type="submit">Save</button>
</form>
);
}

show checked when the option is selected

I have two API, one that returns the list of all permissions and second that returns the list of selected permissions(contains permission Object) now I want to show the list of permissions in checkboxes but if the permission is already selected then show checkmark with it.
component.ts
getUserPermissions() {
this.permissionService.getUsersPermission().subscribe(permission => {
this.permission = permission;
})
}
getAssignedPermissions(uuid: any) {
this.permissionService.getAssignedPermissions(uuid, true).subscribe(res
=>{
this.userPermission = res;
})
}
component.html
<form id="permission" #form="ngForm" (ngSubmit)="onSubmit()" class="form-group">
<div *ngFor="let permission of permission" >
<label>
<input type="checkbox"
value="{{permission.code}}"
[(ngModel)]="permission.Checked"
[ngModelOptions]="{standalone: true}"
/>
{{permission.code}}
</label>
</div>
<button type="submit" class="btn theme-btn btn-secondary">SAVE</button>
You can simplify this by using async-await and iterate through permissions to check whether user permission is existing.
async getAllPermissions() {
this.userpermission = await this.permissionService.getUsersPermission().toPromise();
this.permission = await this.permissionService.getAssignedPermissions(uuid, true).toPromise();
this.permission.forEach(permission => {
if (this.userPermission.find(uPermission => uPermission === permission)) {
permission.Checked = true;
}
})
}
You can use a method that check if the permission is already assigned
<form id="permission" #form="ngForm" (ngSubmit)="onSubmit()" class="form-group">
<div *ngFor="let permission of permission" >
<label>
<input type="checkbox"
value="{{permission.code}}"
[ngModel]="permission.Checked || isassigned(permission)"
(ngModelChange)="permission.Checked = $event"
[ngModelOptions]="{standalone: true}"
/>
{{permission.code}}
</label>
</div>
isassigned(permission) {
const p = this.userPermission.find(p => p.code === permission.code)
return this.userPermission.find(p => p.code === permission.code) ? true: false
}
live code
You should just use [] for ngModel
<form id="permission" #form="ngForm" (ngSubmit)="onSubmit()" class="form-group">
<div *ngFor="let permission of permission" >
<label>
<input type="checkbox"
value="{{permission.code}}"
[ngModel]="permission.Checked"
[ngModelOptions]="{standalone: true}"
/>
{{permission.code}}
</label>
</div>
<button type="submit" class="btn theme-btn btn-secondary">SAVE</button>

AngularJS validation message and showing no results and results div issue on submit

The following form shows a list of data on submit. I am trying to show no results found when there is no data on submit. I tried like shown below,it shows and hides the div. But when there is no options selected on form and click submit button it shows the no result div.How to show the no results div only when form validation succeeds and there is no data to display.
HTML
<div class="form-group" >
<label class="radio-inline">
<input name="sampleinlineradio" value="3" type="radio" ng-model="radioption"
ng-required="!radioption"> MAIN 1</label>
<label class="radio-inline">
<input name="sampleinlineradio" value="1" type="radio" ng-model="radioption" >
Main 2</label>
<div ng-show="!radioption && buttonClicked">Please select one.</div>
</div>
<div class="form-group">
<label ng-repeat="branch in branches">
<input type="checkbox" name="selectedBranches[]" value="{{branch.value}}"
ng-model="branch.selected" ng-required="isOptionsRequired()" >
{{branch.name}}</label>
<div ng-show="isOptionsRequired() && buttonClicked">Please select one.</div>
</div>
<input type="button" ng-click="fetchresults()" value="submit" >
<div ng-show="buttonClicked">
<table> <thead>.....</thead>
<tbody>
<tr ng-show="results.length!=0" ng-repeat="r in results">
<td></td></tbody></table>
</div>
<div ng-show="buttonClicked">
<span ng-show="results.length==0 ">No results.</span>
</div>
Minimal Controller Code
$scope.fetchresults = function(){
$scope.results = Result.query({main: $scope.radioption, branch: $scope.selection[0], });
$scope.buttonClicked = true;
}
EDIT:
I used model to validate and $valid is also working, as suggested below.But Got a couple of glitches. If i click the button it does not show div. but after validation is over it shows automatically "no results" from the click before. How to stop this.And while it lists data when its available it shows "no results" for a second or so
Give your form a name
<form name="formName">
Then you can do
ng-show="results.length==0 && formName.$valid"
Some more information on angularJS form validation
You can check the below snippet, I have changed most of them in angular way with $invalid, $pristine, $submitted and $valid.
You can check the angular documentation to read about them.
Link 1, Link 2
Note: You can use a submit button and get rid of ng-click event and use ng-submit instead which can't be used in this snippet as form submit is not allowed. Comment the line form.$submitted = true; when you use a submit button.
var app = angular.module('app', []);
app.controller('TestController', function($scope){
$scope.isFieldInvalid = function(field) {
var form = $scope.testForm;
return form[field].$invalid && (!form[field].$pristine || form.$submitted);
};
$scope.fetchResults = function(){
var form = $scope.testForm;
form.$submitted = true; // comment this line if button type="submit"
if(form.$valid){
$scope.searching = true;
$scope.results = [];
var rnd = Math.random();
if(rnd >= 0.5) {
$scope.results = [{id: 1}, {id: 2}];
}
//$scope.results = Result.query({main: $scope.radioption, branch: $scope.selection[0], });
$scope.buttonClicked = true;
$scope.searching = false;
}
};
});
angular.bootstrap(document, ['app']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form name="testForm" ng-controller="TestController" ng-submit="fetchResults()" role="form" novalidate="">
<div class="form-group" ng-controller="TestController">
<label class="radio-inline">
<input name="sampleinlineradio" value="3" type="radio" ng-model="radioption" ng-required="true"> MAIN 1</label>
<label class="radio-inline">
<input name="sampleinlineradio" value="1" type="radio" ng-model="radioption" ng-required="true" >
Main 2</label>
<div ng-show="isFieldInvalid('sampleinlineradio')">Please select one.</div>
</div>
<div class="form-group">
<label ng-repeat="branch in branches">
<input type="checkbox" name="selectedBranches[]" value="{{branch.value}}"
ng-model="branch.selected" ng-required="isOptionsRequired()" >
{{branch.name}}</label>
<div ng-show="isOptionsRequired() && buttonClicked">Please select one.</div>
</div>
<input type="button" value="submit" ng-click="fetchResults()" >
<div ng-show="buttonClicked && !searching">
<table> <thead></thead>
<tbody>
<tr ng-show="results.length!=0" ng-repeat="r in results">
<td>{{r.id}}</td></tbody></table>
</div>
<div ng-show="buttonClicked && !searching">
<span ng-show="results.length==0 ">No results.</span>
</div>
</form>

Angular dart radio buttons not binding to model

I have an Angular Dart component with the following html:
EDIT: For some reason some of my html did not copy properly. outside of the label tag I have:
<div class="btn-group btn-group-vertical" data-toggle="buttons">
`
<label ng-repeat="item in items" class="btn btn-primary btn-sm btn-block" ng-show="isItemVisible(item)">
<input type="radio" name="options" value="{{item}}" ng-model="selected">{{item}}
<span class="badge pull-right"><span class="glyphicon glyphicon-ok"></span></span>
</label>
</div>`
However, this never updates the model. I have also tried using onclick, ng-click, and ng-change with the same result- the functions never get called. Is there some directive that I'm using incorrectly?
Use Future in your ng-click so it will allow your model to get updated.
<input type="radio" name="options" value="{{item}}"
ng-model="selected" ng-click="radioButtonClicked();">{{item}}</input>
//Component Code:
void radioButtonClicked(){
new Future((){
//Use your selected model here.
});
}
$parent should do the trick. Here is working example:
HTML
<div>
<div ng-repeat="item in items">
<label for="{{item.name}}">{{item.name}}:</label>
<input id="{{item.name}}" type="radio" ng-model="$parent.$parent.selected" ng-value="item.value" />
</div>
<strong>Selected value:</strong> {{$parent.selected}} <br/>
</div>
Controller
$scope.items = [{
name:'Item1',
value: 'value1'
}, {
name:'Item2',
value: 'value2'
}, {
name:'Item3',
value: 'value3'
}];
$scope.selected = null;