Custom validation message with React Select - javascript

I want to internationalize the form validation messages. I managed to do that for standard inputs using this solution. For React Select, though, it's behaving a little differently. Apparently, all that is needed is to override onChange and onInvalid inside an inputProps prop.
However, it seems that the embedded <input/> doesn't fire its onChange function when its value changes. That means that, once the Select is invalid, it never changes back to valid. Another thing that might be related is that the embedded <input/>'s value is null after an option is selected.
Here is a CodeSandbox that shows how far I've got. The first Select works as expected, but with the default validation message. The second Select have a custom message, but doesn't work as expected. The <input/> is there to show that onChange is not being called in the embedded <input/>.
Please let me know if it's possible to make it behave as expected.
Thanks in advance.

I managed to do something usable but, as I said in comments, it's not pretty. If that link goes dead, it involves setting required to true/false in order to try to make the message appear only once, and using setCustomValidity whenever the message inevitably appears.
I'll raise an issue in React Select because I think there has to be a better way, as it's shown in the example with pure <input/>.

Related

vuejs-datepicker Typeable Input submit delay

I have am using the Vuejs-datepicker
The problem I am having is I want to use a typable input as well as the datepicker, but when I type into this input field it fires the keyup event which triggers its v-on:selected event.
Meaning if I start typing in '2012-02-02' with it submits on ever key up.
Usually this would be easy to solve as you can use a .length but this vue component always hands back a Date that is parsed. So that won't work.
I have the idea to deconstruct the component and build my own but was hoping someone might have an idea for a different solution
Did you tried the Event Modifiers?
You could try to use then in #keyup, something like #keyup.prevent...
Se at, look for "Event Modifiers":
https://v2.vuejs.org/v2/guide/events.html

How to trigger async. validation in redux-form?

I am using asyncBlurFields. I tried following actions: change, startAsyncValidation, touch, blur. None is triggering the async validation. Then I read redux-form doesn't work well with hidden inputs, so I changed type to text and it is still not working. Only time when async. validation is triggered is when user blurs the element.
Is my only option to add ref to a form instance, dig out asyncValidate, get all required parameters manually and call it myself? I hope there is a better way, I don't want to add lengthy hacks to many forms. And that is my question:
How to easily trigger asyncValidate without calling it with all its parameters myself?

How to send keystrokes to a textbox that remains hidden until it's clicked on?

I'm trying to log into this site. But I can't even fill the textbox with the username.
I tried:
implicit and explicit waits
executing JavaScript
Structure of the textbox
The username is enclosed within a td tag, which can be located using its width attribute. The textbox itself is represented by two input tags. The first one is hidden. Both have style attributes. The first one has an initial value of display: none;, which is changed to display: inline-block; when I click on the textbox. And the style attribute of the second input tag is set to display: none;. Again, both these are toggled once the username textbox loses focus.
Waits
I tried using both implicit and explicit waits. The code implementing explicit wait resulted in a TimeoutException error:
wait = WebDriverWait(driver, 10)
elem_username = wait.until(EC.visibility_of_element_located((By.ID, 'txt_username')))
Executing JavaScript
Both the input tags have onfocus and onchange attributes. I didn't bother about the latter (my goal was to get keystrokes into the textbox first). The onfocus has a value of SetEnd(this). So, I tried to execute that.
The problem I had is that I couldn't find any documentation that could help me executing JavaScript. So I looked at a few related answers here at StackOverflow. I tried this first:
elem_username = driver.find_element_by_id('txt_username')
driver.execute_script('SetEnd(this)')
Of course, I knew it wouldn't work, because I was not referring to the element. So after browsing a few more questions, I learnt that execute_script took arguments. So I modified the code, which raised an error that said something like the script had no function like this:
driver.execute_script('arguments[0].SetEnd(this)', elem_username)
Then, I saw an answer using 'click()' inside the execute_script; so I tried that, too:
driver.execute_script('arguments[0].click()', elem_username)
The 'click()', I guess, is only for buttons. But since I had to "click" in the textbox to bring it in focus, I thought it would work. It didn't.
This is the last line I executed in all of my attempts, which, without an exception, kept raising ElementNotInteractableException error:
elem_username.send_keys('blahblahblah')
Requirements
The Q&As on this site would, of course, be excellent, if I had a bit more experience. For instance, there are several answers demonstrating explicit wait, but most of them were aimed at solving the OP's problem, and hence they included only the relevant parts of code. It was tough for me to understand them.
I want to solve this problem (logging into the site), but I also want to learn working with selenium properly. I haven't worked with it earlier in any other languages such as Java. The official documentation is good, but I couldn't solve this problem using that. So I want a more beginner-friendly tutorial.
This worked for me:
# Force the element to be displayed (noticed style.display = "none")
# Yes, I know you can see it, but selenium thinks it's not displayed.
driver.execute_script('document.getElementsByName("txt_username")[0].style.display="block"')
elem_username.send_keys('your name')
So you've outlined everything well and you seem to have a good understanding of it. The trick is to click the second input first, then send keys to the first input since it is then focused. (I did find that clicking the containing td also worked for Chrome, but browsers are different in that aspect and the intent of this page is that you click on the second input). A simple solution is as follows:
real, readonly = driver.find_elements_by_css_selector("input[onfocus*='SetEnd']")
readonly.click()
real.send_keys('hi')
If you have any questions about that, I can try to help.

Trigger TypeAhead suggestion selection

For the life of me I cannot figure out how to trigger a suggestion selection on a TypeAhead input
I've tried all kinds of things like
.trigger('suggestionClicked', $('.tt-dropdown-menu .tt-suggestion:nth-child(1)'))
I suppose there are really two parts to this problem.
1. Properly selecting the actual TypeAhead object.
I do this primarily by focusing (focus()) on the input field, and then using jQuery to find the element that is active ($(document.activeElement)). This might not be the best way. It's quite difficult to test in the browser web-inspector because every time I go to the console I lose focus and then the menu disappears (literally removing the results from the DOM)
2. Triggering the correct event.
I'm not sure exactly on which object or which event to trigger, but my best guess is either suggestionClicked on either the TypeAhead object or the TypeAhead.Dropdown object. Second best guess would be click.tt.
I might be overthinking this.
If you really care about the reason behind this, it's because I need to test the functionality via Capybara/Selenium.
I've been browsing the source code on github for some insight.
Here is a step in my Capybara attempt. I feel like I'm getting close but it's not there yet.
steps.rb
Then /^I select result number "([^\"]*)" from typeahead$/ do |num|
find('.tt-dropdown-menu')
#within('.tt-dropdown-menu') do
page.execute_script %Q{$(document.activeElement).dropdown().trigger('suggestionClicked', $('.tt-dropdown-menu .tt-suggestion:nth-child(#{num})'))}
#end
end

Can't disable (set to read-only, protect, gray-out etc.) a field

I've run this code:
Xrm.Page.data.entity.attributes.get("subject").setValue("Beep");;
alert(Xrm.Page.ui.controls.get("subject").setDisabled);
Xrm.Page.ui.controls.get("subject").setDisabled(true);
As expected, I get the text Beep into the field. As expected, the alert tells me the contents of the method (and as far I can tell, they're doing what they're supposed to).
However, the Control itself doesn't get disabled. What am I doing wrong?
I believe that I saw one example of different approach (something more between get and setDisabled but after a few hours of googling, I'm starting to conclude that I must've been halucinating or wish-thinking.
Your code is correct, so it should be working. The syntax used by #Daryl is correct to. Those two lines are equivalent. The shorter one is just syntactic sugar shortening the other. So, you should use his.
Xrm.Page.ui.controls.get("subject").setDisabled(true);
Xrm.Page.getControl("subject).setDisabled(true);
If you're alerting out and getting the contents of the method, it means that you're hitting the right component and the correct method. Yet, so say that despite the call, the control doesn't get disabled. I think you're wrong.
Here's what I think happens. The control gets disabled, then, before you have time to notice it, the form get updated, rendering away your disable operation.
Keep in mind that unlike the field data, the property of being disabled doesn't get stored to the database. If you design a field as protected, it'll stay that way. But if you set such a property from the JavaScript code on the client-side, the appearance is only going to last until a reload of the page is performed.
So, if you need to keep the fields disabled, either make them so from the GUI designer or fire an onLoad method doing it for you.
I use the getControl function and it works fine. should be in the form:
Xrm.Page.getControl(controlId).setDisabled(disabled);
And remember, disabled controls will not be updated unless you set the submit mode to "always".

Categories