I have couple of text_area_field in my application which can be distinguished only by using the value inside it. How can I get a specific element using value?
Ex:
<div data-component="options">
<input data-component="text_area">Value 1</input>
<input data-component="text_area">Value 2</input>
<input data-component="text_area">Value 3</input>
<input data-component="text_area">Value 4</input>
I have tried
cy.get('[data-component="options"] [data-component="text_area"]').contains('Value 3').clear().type('Edited 3').
but it is giving the error :
Timed out retrying: Expected to find content: 'Value 3' within the element: but never did
Any help would be highly appreciated.
Check if the div allows typing. If yes, try the below code and see if that is working:
cy.get('[data-component="options"] [data-component="text_area"]').each(($div, i) => {
const valueText = Cypress.$($div).text();
console.log(valueText);
if(valueText === "Value 3") {
cy.wrap($div).clear().type("Edited 3");
}
})
You could also try using eq(), but if there are changes in selector with more options it may fail.
cy.get('[data-component="options"] > div').eq(2).then(($div)=>{
cy.wrap($div).contains("Value 3").clear().type("Edited 3");
})
You could possibly try this one too:
cy.get('[data-component="options"] > div').contains("Value 3").clear().type("Edited 3");
I think this will work .Try this code:
cy.get('[data-component="options"] > div').invoke('show').eq(2).then(($div)=>{
cy.wrap($div).contains("Value 3").clear().type("Edited 3");
})
Related
<form
class="" id="form" hx-post="/add/" hx-swap="afterbegin" hx-target="#big_list" hx-trigger="submit">
<input type="text" name="langue1" >
<input type="text" name="langue2">
<div id="errors"></div>
<button type="submit">GO</button>
</form>
<div id="big_list">
.....
</div>
I have a big list in #big_list, and I want my #form appends only one row when submitted.
How with htmx, can I handle errors and show message in #errors ?
I created this solution so you can use hx-target-error = to define which HTML will be displayed after a failed request
document.body.addEventListener('htmx:afterRequest', function (evt) {
const targetError = evt.target.attributes.getNamedItem('hx-target-error')
if (evt.detail.failed && targetError) {
document.getElementById(targetError.value).style.display = "inline";
}
});
document.body.addEventListener('htmx:beforeRequest', function (evt) {
const targetError = evt.target.attributes.getNamedItem('hx-target-error')
if (targetError) {
document.getElementById(targetError.value).style.display = "none";
}
});
If your code raises the errors (validation?), you can change target and swap behavior with response headers.
Response.Headers.Add("HX-Retarget", "#errors");
Response.Headers.Add("HX-Reswap", "innerHTML");
If you want to return a status other than 200, you have to tell htmx to accept it.
4xx would normally not do a swap in htmx. In case of validation errors you could use 422.
document.body.addEventListener('htmx:beforeOnLoad', function (evt) {
if (evt.detail.xhr.status === 422) {
evt.detail.shouldSwap = true;
evt.detail.isError = false;
}
});
It works in htmx 1.8.
If you want to remove the error message on then next sucessfull request, you could use hx-swap-oob. Out of band elements must be in the top level of the response.
So the response could look like this:
<div>
your new row data...
</div>
<div id="errors" hx-swap-oob="true"></div>
Update
You can now use the new powerful extension multi-swap to swap multiple elements arbitrarily placed and nested in the DOM tree.
See https://htmx.org/extensions/multi-swap/
Although it doesn't follow REST principles, you might consider using an swap-oob to report your error back to your user. For example, your request might return a (slightly misleading) status 200, but include content like this:
<div id="errors" hx-swap-oob="true">
There was an error processing your request...
</div>
If it's important to follow REST more precisely, then you'll want to listen to the htmx:responseError event, as mentioned by #guettli in his previous answer.
I have an array of names, and if a user try to update one of them and is duplicate, I want to do something (error message) The problem is that is always duplicate. Pname will be changed on every keypress. I am not sure how to store the initial array and to compare with it.
<input
v-model="Pname"
type="text"
class="form-control"
/>
for(let element of this.customer_names){
if(this.Pname == element.name){
duplicateValue = +1;
}
}
You can do something as simple as:
if(this.customer_names.indexOf(this.Pname) != -1) {
// there is a duplicate somewhere
}
Put that code in your change/key-up event listener
You can use #blur like this:
<input
v-model="Pname"
type="text"
class="form-control"
#blur="findDuplicate"
>
function findDuplicate () {
if(this.customer_names.indexOf(this.Pname) != -1) {
// There is a duplicate
}
}
So, by this when you click outside, after you are done with typing, it will run that findDuplicate function.
Tried several solutions before posting, but none seems to be working and I must be doing something wrong.
My code is as follows (simplified)
<label>
<input type="checkbox" id="menu-image-settings-container" value="1" name="..." checked="checked">
Add image?
</label>
<div class="image-settings">show content if checked</div>
js code
$( ".image-settings" ).hide();
var wrapper = $(this).closest('li.menu-item');
if ( $('input#menu-image-settings-container').is(':checked') ) {
wrapper.find('.image-settings').show();
console.log('is-checked');
} else {
wrapper.find('.image-settings').hide();
console.log('is-not-checked');
}
$('input#menu-image-settings-container').change(function(){
if(this.checked) {
wrapper.find('.image-settings').show();
} else {
wrapper.find('.image-settings').hide();
}
});
console.log says is-not-checked, while it clearly is in the source code.
I've tried using if ($('input#menu-image-settings-container').is(':checked')) {...} but that didn't worked either, while normally that should work as well.
First, is(':checked') is a correct solution. Here's why: https://stackoverflow.com/a/7672031/9145243
And you can see that in this part of code your console.log works.
The actual problem is in this construction: wrapper.find('.image-settings').hide(); This code just can't find your .image-settings element.
I've replaced it with $('.image-settings') just to show you that the problem was here.
$('input#menu-image-settings-container').change(function() {
if($(this).is(':checked')) {
$('.image-settings').show();
} else {
$('.image-settings').hide();
}
});
When you debug your code it's a good practise to always use console.log, line by line. And then you will clearly see where exactly you have a problem
I'm using Meteor Blaze and Bootstrap 3 to display an img with a tooltip on mouseover. It works fine with a static tooltip text:
<img class="socialMediaIcon" src={{iconPath}} data-toggle="tooltip"
data-placement="right" title={{tooltip}} />
but I want to dynamically change the tooltip depending on the value of a Collection document field.
I've created a template helper to generate the desired text:
Template.SocialMedia.helpers({
getSocialMediaIconTooltip: function(service) {
console.log(">>>>>> Tooltip service =", service);
var smsdata = socialMediaSystem.findOne({service: service});
if (!smsdata.active)
return smsData.tooltip;
else {
var smudata = socialMediaUser.findOne({accountId: Meteor.user()._id, service: service});
if (smudata)
return "Disconnect " + smsData.tooltip;
else
return "Connect " + smsData.tooltip;
}
},
and I'm calling it with:
<img class="socialMediaIcon" src={{iconPath}} data-toggle="tooltip"
data-placement="right" title={{getSocialMediaIconTooltip name}} />
where "name" is a field in the open document (the code is inside a {{#each}} loop). "name" is non-blank and is used successfully later in the #each block. "getSocialMediaIconTooltip" never gets called and no tooltip appears. I've used this argument passing syntax in other places that work. What am I doing wrong?
The helper might be throwing an error, and in Blaze templates this means blank output (i.e. no tooltip). Check the browser console for error messages.
Your helper refers to both smsdata and smsData. Is that correct, or is smsData an invalid reference?
Typos on my part, see comment above. The corrected code for reference:
Template.SocialMedia.helpers({
getSocialMediaIconTooltip: function(service) {
try {
const smsdata = socialMediaSystem.findOne({subname: service});
if (smsdata.active == false)
return smsdata.tooltip;
else {
const smudata = socialMediaUser.findOne({accountId: Meteor.user()._id, service: service});
if (smudata)
return "Disconnect " + smsdata.tooltip;
else
return "Connect " + smsdata.tooltip;
}
} catch(ex) {
console.error(ex);
}
},
Neither works this one:
$formTemplateModal.modal('show');
$('#form_template_name').focus();
nor a more complicated one:
$formTemplateModal.modal('show').promise().done(function() {
// #todo: does not work.
$('#form_template_name').focus();
});
field $('#form_template_name') is a input[type=text] and it surely exists and it belongs to $formTemplateModal.
The shown is changed in bootstrap 3 ,
Try this if it could help
$('#myModal').on('shown.bs.modal', function () {
$('#textareaID').focus();
})
this is more easier try using the autofocus in your tag .
<textarea id="textareaID" autofocus="" ></textarea>