When I try to reset a field with cy.clear() and the element is a dropdown,
it is failed because it requires a valid clearable element.
When('#userSettings.actions I reset Gender', () => { userSettings.form.getGenderDropdown().clear(); });
Cypress gives the error as, /
cy.clear() failed because it requires a valid clearable element.
Please see How do I clear a multi-select input using Cypress.
There is usually an input underlying a dropdown, so possible suggestions you might use -
userSettings.form.getGenderDropdown()
.invoke('val', '')
.trigger('change')
userSettings.form.getGenderDropdown()
.find('input')
.invoke('val', '')
.trigger('change')
Some other suggestions floating around, but a little bit dubious -
userSettings.form.getGenderDropdown()
.type({selectall}{backspace})
userSettings.form.getGenderDropdown()
.select([])
I notice in the Cypress test clear_spec.js
context('works on input type', () => {
const inputTypes = [
'date',
'datetime',
'datetime-local',
'email',
'month',
'number',
'password',
'search',
'tel',
'text',
'time',
'url',
'week',
]
inputTypes.forEach((type) => {
it(type, () => {
cy.get(`#${type}-with-value`).clear().then(($input) => {
expect($input.val()).to.equal('')
})
})
})
})
which is a pretty long list of valid types, so if you do have an input behind the form control this might be all you need
userSettings.form.getGenderDropdown()
.find('input')
.clear()
This snippet does the job. Please learn it and try to modify it for you. I selected one of the available options, then deleted 'disabled' atrribute from the default option to select it in future.
it('example', function () {
cy.visit('https://www.seleniumeasy.com/test/basic-select-dropdown-demo.html');
cy.get('[id="select-demo"]').select('Monday')
cy.get('[id="select-demo"]').find('option').eq(0).then(($elem) => {
$elem.removeAttr('disabled')
})
cy.get('[id="select-demo"]').select('Please select')
})
One way is to reset the form, presuming clearing the whole form is what you are aiming for.
Please see HTMLFormElement.reset()
The HTMLFormElement.reset() method restores a form element's default values. This method does the same thing as clicking the form's reset button.
If a form control (such as a reset button) has a name or id of reset it will mask the form's reset method. It does not reset other attributes in the input, such as disabled.
HTML
<form>
<select class="form-control" id="select-demo">
<option value="" selected="" disabled="">Please select gender</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Unknown">Unknown</option>
</select>
</form>
Test
it('resets the form values', () => {
cy.get('select').should('have.value', null); // starts with empty value
cy.get('select').select('Female') // select an option
.should('have.value', 'Female');
cy.get('form').then($element => $element[0].reset())
cy.get('select').should('have.value', null); // now empty again
})
Related
I am trying to select a different value from a dropdown and checking a logic based on the newly selected text from the dropdown list and comparing the text entered in a textbox. If the selected dropdown text and the text box value fails the logic, i want to revert back to the original text that was previously showing in the dropdown box.
For ex: In my dropdown box, i have values as "Valid", "Invalid", "PCR IN", "PCR OUT" and the dropdown already displays "Valid". If the user changes the value from "Valid" to "PCR IN" and the 2nd textbox value if changed to a negative number, i am throwing an error via bootbox to the user, saying the textbox value should be in positive.
But i needed to change the original value to "Valid" that was showing in the dropdown before the user changed to "PCR IN". My code is not functioning as desired. It puts a empty result in the dropdown [attached]
My code below:
My MVC View page for creating the dropdown model:
#Html.DropDownListFor(model => model.FundingStatusId, new SelectList(ViewBag.FundingStatusDdl, "FundingStatusId", "FundingStatusName"), "Select Fund Status", htmlAttributes: new { #class = "form-control rtscustomtextboxright", #id = "fundingstatus" })
$(function () {
var fundingStat = $("#fundingstatus option:selected").text();
$("#fundingstatus").change(function () {
if ($("#fundingstatus option:selected").text() == 'PCR IN') {
// debugger
if (parseFloat($('#additionalFunds').val(), 10) > 0) {
bootbox.alert({
title: "ERROR - Please fix this",
size: "lg",
message: "<br><br><br>Additional Funds must be a NEGATIVE $ amount"
})
// return false;
$("#fundingstatus").val(fundingStat);
}
}
})
});
I believe you're using the .val() method wrong.
var fundingStat = $("#fundingstatus option:selected").text();
$("#fundingstatus").val(fundingStat); // you set the val for the option's text and not its value.
You don't mention the dropdown's code in your question so I can't write the fix but checkout the following explanation:
if we have the following dropdown:
<div class="test">
<select>
<option value="a">First Choice</option>
<option value="b">Second Choice</option>
<option value="c">Third Choice</option>
</select>
</div>
In order to set the selected option we should use the .val() with the value and not the text().
$(".text select").val("b"); // will select the "Second Choice"
And not:
$(".text select").val("Second Choice");
Edit:: What I am trying to achieve is I am getting each option text not the value, so I can send it to an API. Getting the text from the select works perfectly. I want to remove it when I deselect an option from the input value when I click it again. For example if I select multiple I get Medit-4-packs, Swiss-Gear-Bag When I click it one by one it removes it but when I deselect multiple I get the value of another. I want to replace the value as empty when deselected like usual. Hope it helps to clarify
Any help on using jquery to deselect Select option from input value? These are what I have tried so far. Thanks for help
Trying to remove the values in the <input> when option gets deselected.
<input class="form-check-input" type="text" value="" id="equipment" name="equipmentitems" >
<select multiple class="image-picker show-labels show-html" data-limit="16" name="packages[]" id="group_psoft">
<option value=" " data-img-class="first" selected></option>
<option data-img-src="/images/" data-img-label="Scanner Tips(4Pcs)" name="packs" data-img-alt="KeepSame" value="400" >Medit-4-packs</option>
<option data-img-src="/images/" data-img-label="SwissGear Bag" name="bagoriginal" data-img-alt="Aggresive" value="200"> Swiss-Gear-Bag</option>
</select>
Js
$('.image-picker').imagepicker({
show_label: true,
limit: 15,
//This is setting the text in the input
selected: function($items) {
$('#equipment').val($(this).find('option:selected').text());
},
// Here I want to remove it if clicked again
changed: function(){
$('#equipment').val($(this).unbind('option:selected').text()); // This removes it but add all the other options text in the input
$('#equipment').val($(this).unbind('option:selected').val( )); // Here It removes it but I get the value of the next selected option.
$('#equipment').val($(this).unbind('option:selected').text(' ' )); This I get Js [object,object]
}
});
I solved it when I move the code outside the function. I also changed unbind() to on() method.
$('.image-picker').on('change', function() {
$('#equipment').val($(this).find('option:selected').text());
});
Try this and see if it works out.
$('.image-picker').imagepicker({
show_label: true,
limit: 15,
//This is setting the text in the input
selected: function($items) {
$('#equipment').val($(this).find('option:selected').text());
},
// Here I want to remove it if clicked again
changed: function(){
var equiValue = $('#equipment').val();
var selectedValue = $(this).find('option:selected').text();
if(equiValue === selectedValue) {
$('#equipment').val("");
}
}
});
I'm using ant design. I have a form. In that form I have submit button and select dropdown.
when I click submit button it triggers the form submit action.
I need to submit form and get values on select change event.
Code sandbox: https://codesandbox.io/s/xrpzw7wn8q
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log("Received values of form: ", values);
}
});
};
I will try to answer this question in a more general way because it pops in the search results and it may help some people.
To submit a select form on a change event (without a submit button) in React, you have to do two things:
use the "onChange" property to fire a function to send the value.
in this function, you have to trigger the submit action of the form.
To do number 2, in classical javascript you would grab a reference to the form and then use the submit() method. In React, to grab the form, you can use "useRef". The submit() method is then accessible on the "current" property. Here is an implementation:
import { useRef }, React from "react"
export default function SelectOnChange () {
const selectForm = useRef(null)
const handleSubmit = () => {selectForm.current.submit()}
return (
<form ref={selectForm} method="get" onChange={handleSubmit}>
<select name="sort" id="sort">
<option value="relevance">Relevance</option>
<option value="score">Score</option>
</select>
</form>
)
}
You can add a callback to the onchange event of the Ant Design Select component, that could handle the form submit:
<Select
allowClear
onChange={
(value) => {
// your code to submit the form
}
}
>
<Option key={1} value={1}>
something 1
</Option>
<Option key={2} value={2}>
something 2
</Option>
</Select>
BUT from an UX perspective, if the submit button has to be present, it should be it to trigger submitting
You can do something along those lines:
<Select allowClear onSelect={ (val, event) => this.handleSubmit(event) }>
Add the onChange() or onSelect() from ant design select and access the values from the form in the callbacks.
state={
selectValue : "default value",
otherFormItemValue: "default other value"
}
handleSubmit = () => {
serviceCallToSubmitForm(this.state.selectValue, this.state.otherFormItemValue);
}
//In the render() of component
<Select
onChange={
//or onSelect
(value) => {
this.setState({selectValue: value});
this.handleSubmit()
}
}
>
<Option key={1} value={"value 1"}>
something 1
</Option>
<Option key={2} value={"value 2"}>
something 2
</Option>
</Select>
<Button onClick={this.handleSubmit}>Submit</Button>
Hope this helps and is clear enough.
The handleSubmit function is used to access the form values from the state and submit it.
The onChange function call it used to :
1. Store the dropdown value in the state
2. call the handleSubmit function to actually submit in the same action [not recommended UX-wise]
Here is code sandbox.
https://codesandbox.io/s/r00v7x8r7q
Select dropdown item and check console for the respected value.
Getfield decorator doesn't have onchange option, so remove it and add onchange event to select tag instead of getfield decorator.
Check ant docs for available options.
https://ant.design/components/form/
getFieldDecorator(id, options) parameters
<select class="distinctrank" name="rank[]" required>
<option value="">Select</option>
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>
<select class="distinctrank" name="rank[]" required>
<option value="">Select</option>
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>
<select class="distinctrank" name="rank[]" required>
<option value="">Select</option>
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>
I am trying to prevent the user to select the same option twice
EX:
value 1 -> B
value 2 -> C
value 3 -> A
But not allow
value 1 -> B
value 2 -> B
value 3 -> A
I can't use this: answer
because I have 8 <select> with 8 <option>and the user is allow to change his/her option.
Unfortunately, I can't use a single select set to "multiple".
I found this answer just now, but since I don't jquery or Javascript well, I can't make it work without the select tag inside a table:
Here is the answer
UPDATE:
I found a better way to do it, but I am having some problems.
I tried to modify this code: with input tags to make it work with select tags. The problem that I am facing now is that every time you select the same option twice, the error "Please enter a Unique Value" show up (I do want to see it, when the user select the same value twice or more) and when you change the value the "Please enter a Unique Value" does go away. But, It keep a "this field is required" warning behind (when a click a new select tag). So, "this field is required" doesn't go away until the user pick an option for all select tag.
Here is the Jquery code:
jQuery.e
jQuery.validator.addMethod("notEqualToGroup", function(value, element, options) {
// get all the elements passed here with the same class
var elems = $(element).parents('form').find(options[0]);
// the value of the current element
var valueToCompare = value;
// count
var matchesFound = 0;
// loop each element and compare its value with the current value
// and increase the count every time we find one
jQuery.each(elems, function() {
thisVal = $(this).val();
if (thisVal === valueToCompare) {
matchesFound++;
}
});
// count should be either 0 or 1 max
if (this.optional(element) || matchesFound <= 1) {
//elems.removeClass('error');
return true;
} else {
//elems.addClass('error');
}
}, jQuery.validator.format("Please enter a Unique Value."))
// validate form
$("#signupform").validate({
rules: {
'rank[]': {
required: true,
notEqualToGroup: ['.distinctrank']
},
},
});
I wonder if you could simply use a single select set to "multiple"...
<select multiple class="form-control" name="rank[]">
<option value="">Select</option>
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>
It seems appropriate :-)
Your code...
rules: {
'rank[]': { // <-- will only match one of your three
required: true, ....
You cannot have three different select element all share the same name, in your case, rank[].
The jQuery Validate plugin requires that every form data input element contain a unique name. It's how the plugin keeps track of the form inputs, and there is no workaround for this. You'll have to include an index or change the name.
rules: {
'rank[1]': {
// rules
},
'rank[2]': {
// rules
},
'rank[3]': {
// rules
}
}
If the same rules are used on all three, then you can use the .rules() method to apply them all at once...
$("#signupform").validate({ // plugin initialization
// other rules & options
});
$('[name^="rank"]').each(function() {
$(this).rules('add', {
required: true,
notEqualToGroup: ['.distinctrank']
});
});
$('[name^="rank"]') matches all elements that have a name that "starts with" rank. Then .each() applies the rule to every instance matched by the selector.
You can try something like this:
$(document).ready(function() {
$('select').change(function() {
self = $(this);
choosen = $(this).val();
$('select').not(self).each(function() {
if ($(this).val() == choosen) {
// $(this).prop('disabled', true);
alert('Option is already selected');
$(self).val($(this).find("option:first").val());
}
});
});
});
This is actually partial implementation of code you found in another answer. Commented line would disable already selected options, but... then users can't change their minds... However i would probably use that commented line (edit:probably not, it causes other problems), rather than annoying alerts -> because, with alerts - if user tries to change his mind - user experience is not so great, again...
DEMO: http://jsfiddle.net/dq9j4s32/2
Another day with another question. I'm working again on my web application. Now I got a problem. THe 'required' attribute is not supported in major browsers
(http://www.w3schools.com/tags/att_select_required.asp)
, it only works if the first option value is empty. Well that works fine, the submit event does nothing if the form is $invalid and it is when it's left by "Please select".
Land*:<br />
<select id="countries" name="country" data-ng-model="contact.country" required required-select>
<option value="">Please select</option>
<script type="text/javascript">
$(document).ready(function () {
var countries = {};
if (countries.length > 0) {
return countries;
} else {
$.get('WebKalkTool/country_de.xml', function(data) {
countries = data;
var that = $('#countries');
$('name', countries).each(function() {
$('<option />', {
text: $(this).text(),
}).appendTo(that);
});
}, 'xml');
}
});
</script>
</select>
<span class="error" data-ng-show="mandatory">Please select an item</span>
</p>
What I'm searching is a directive which checks if the value is empty, and then shows
the error after submit and if they select an item, the error vanishes.
Now the directive should maybe look something like this:
authApp.directive('requiredSelect', function () {
return {
require: 'select',
link: function (scope, formElement, attr, formSelect) {
console.log('FORM : Linker called');
console.log(formSelect);
console.log(formSelect.selected.value); // is undefined..
scope.$watch(formSelect.selectedIndex.value, function () {
console.log("index changed"); // Always log when another index is selected
if (formSelect.selectedIndex.value == "") {
console.log("value="");
// only show error after submit OR has visited on span id mandatory (or add new template?
// Tell the form, it's invalid, select is invalid
} else if (formSelect.selectedIndex.value != "") {
console.log("index > 0");
// everything is fine, select is valid
} else {
console.log("FORMSELECT.SELECTINDEX = UNDEFINED");
// just 4 testing my link
}
});
}
};
});
I took out the HTML5 validation because of compatibility thoughts and HTML5 validation shows only the first hint anyway.
It should be something equals like 'required' attribute for input fields and work the same way, I don't want to make my submit button disabled. Maybe I also can remove this "Please Select" option and leave it empty.
Or maybe I'm just not that clever enough to do something equal like:
<span class="error" data-ng-show="requestForm.place.hasVisited && requestForm.place.$invalid">Required!</span>
Doesn't matter if we check the value or the selectedIndex, whatever.
Thanks for your help and regards
Anthrax
AngularJs already know how to treat the required attribute (see here). In your case you might want to do something similar to that :
<form name="myForm">
<select name="country"
ng-model="country"
ng-options="c.name for c in countries"
required>
<option value="">-- chose country --</option>
</select>
</form>
Then up to you to display an error message when your form and/or select is marked as invalid by Angular or after a click on the submit button.
// Inline validation appears directly when select value is empty
<span class="error" ng-show="myForm.country.$error.required">Required!</span>
// Or after a click on submit, assuming you have set a boolean to show/hide error
<span class="error" ng-show="validationFailed">Required!</span>
I have assembled a working example with the 2 possibilities here.