I want to be able to simulate a user typing into a text box using reactjs so that I can test my validation status messages.
I have a react component which validates on keyUp
Below is a simple example of what I've tried.
nameInput.props.value = 'a';
React.addons.TestUtils.Simulate.keyUp(nameInput);
React.addons.TestUtils.findRenderedDOMComponentWithClass(component, 'has-error');
This doesn't seem to change the value of the bound textbox when I debug in the validator
React.addons.TestUtils.Simulate.keyUp(nameInput, {key: 'a'});
React.addons.TestUtils.findRenderedDOMComponentWithClass(component, 'has-error');
This doesn't either.
Could someone point me on the right track, the second is inline with the documentation I could find around simulate (http://facebook.github.io/react/docs/test-utils.html), the first makes sense to me (set the actual textbox value then fake an event)
By setting nameInput.props.value = 'a'; you are not actually updating the value in your component.
You should use React.addons.TestUtils.Simulate.change(nameInput, { target: { value: 'a' } }); or something similar to simulate modifying the actual value.
I found that this syntax works better for me:
const emailInput = component.refs.userEmailInput;
emailInput.value = 'test#gmail.com';
Simulate.change(component.refs.userEmailInput);
The second line updates the input with the text, 'test#gmail.com'. The last line triggers the change.
Related
As described in ScriptUI reference, there are 2 ways to implement changing listener on EditText:
editText.onChanging = function() {
...
}
editText.addEventListener('changing', function(event) {
...
})
However, the function is triggered after an edit to EditText.text has been made, denying opportunity to obtain old text value as a fallback option is new value is undesired. I'm looking for something like this:
editText.onChanging = function(oldValue) {
var newValue = this.text
if (!isCorrect(newValue)) {
this.text = oldValue
}
}
editText boxes have an onActivate callback which is triggered when the element gets focus. If you store the current text value of the editText at that point, it can be returned to its original state if the new value doesn't validate.
Note that it might be worth thinking about the UX hereāif you enter an invalid value, and the value just reverts, you might not realise that it has done so. For the user this could be very confusing: it looks like I enter a value, but nothing happens. It might be better to throw an error, such as a dialog, or disable other controls, e.g. grey out the "do the things" button if the parameters are incorrect.
I am using vue element UI.
and on user input change I want to save data (something like autosave).
So far there is one event provided by element UI, that is "change" event.
But that is also calling when I assign value from backend, in that case data are already saved.
So how to detect whether value has come from user or from our binding (I know I can take flag in this case if there is no other better solution)?
<div id="app">
<template>
<!-- `checked` should be true or false -->
<el-checkbox v-model="checked" #change="changed">Option</el-checkbox>
</template>
var Main = {
data() {
return {
checked: true
};
},methods: {
changed(val) {
alert('This should only change when user inputs, not when data is updated from code');
setTimeout(function(){
//Here alert should not appear as this is not manual input.
this.checked = !this.checked;
},5000);
}
}
};
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
Here is a codepen
https://codepen.io/hnviradiya/pen/zYORGRR
Change event was working perfectly fine.
My mistake was (in code I had written, got answer when I wrote code for question which I took from element ui webpage when asked by #Boussadjra Brahim in comment) that I had bind it using (:) instead of (#).
So it was expecting #change and I had provided :change.
For more details.
https://stackoverflow.com/a/46748348/9263418
Solution 1
The #input event should work well for that case. Small diference is, that it triggeres at each key down.
Solution 2
You could use Vue.nextTick
Before setting the value from backend in code, you could set a flag this.isSettingValue = true. Then you set the value and call Vue.nextTick(() => { this.isSettingValue = false });
Now you can avoid autosaving by checking this.isSettingValue == true.
Using Vue.nextTick ensures that the flag isn't set back to false until after the asynchronous data update completes.
Vue.nextTick( [callback, context] )
I'm trying to write a bookmarklet to autofill a form, to simplify manual testing. The site is implemented in React. I've tried using JQuery, for example:
$("#emailAddress").val("bob#example.com").changed()
While the input field is visibly updated in the browser, it appears that under the hood the field is not recognised as changed, as validation fails on form submit, saying the data is missing.
Is there a workable way to autopopulate the React form fields using ad-hoc JS, without changing any of the source code?
(Note: I understand that this sort of direct manipulation is not the correct way to work with React in general app development. Here, I'm looking for any solution, no matter how hacky, to simplify ad-hoc manual testing).
//find element
let elem = document.querySelector("#emailAddress");
//create event
let event = new Event('input', { bubbles: true });
//set value
elem.value="bob#example.com";
//trigger event
elem.dispatchEvent(event)
From our discussion in the comments, my guess is that you'll want to fire a change event for each input you plan on modifying.
var element = document.getElementById('emailAddress'),
event = {
target: {
value: 'new value for the input'
}
};
element.onchange(event);
I have a working AutoCompleteExtender implementation.
What I want, is that if I have exited the text box, and the list of items have dissappeared, I want to re-display the list from javascript code without having to write something in the text box again (just redisplay list based on current filter value in text box by click on a button or something). I know how to get the AutoCompleteExtender Behaviour object from code, so all I need is to know the javascript API on that object that enables me to redisplay the list.
I have tried this as suggested in the comments on this answer, but not working:
AutoCompleteEx.showPopup();
I have also tried this as suggested in this answer, but not working:
AutoCompleteEx._onTimerTick(AutoCompleteEx._timer, Sys.EventArgs.Empty);
EDIT:
After some investigation in the back end code used by the AutoComplete, I think maybe the problem is that once shown, it checks on future calls if the value in the search box has changed since last time, and if not it doesn't show it again. I have not found out how to come around this. I have tried different approaches to reset the value, and then set the value again, but with no success.
Enjoy :). That's was an interesting task.
function redisplayAutocompleteExtender() {
var extender = $find("AutoCompleteEx");
var ev = { keyCode: 65, preventDefault: function () { }, stopPropagation: function () { } };
extender._currentPrefix = "";
extender._onKeyDown.call(extender, ev);
}
Or you can set EnableCaching property to true on extender and use script below. This solution allows to avoid additional web service call.
function redisplayAutoComplete() {
var extender = $find("AutoCompleteEx");
var textBox = extender.get_element();
textBox.focus();
var showSuggestions = function(){
extender._update.call(extender, textBox.value, extender._cache[textBox.value], true);
};
setTimeout(showSuggestions, 0);
}
I have a multidimensional array of form field ids and which type of error checking they have on them. I want to add a blur event to each of the error fields so when the user leaves it to go to the next field it will make sure the field is valid.
I created a for loop with the blur event creation and an alert to make sure the blur is being created for that field. The alert tells all the fields have the validation added, but when I go to test it on the page, no matter what field I'm leaving the blur event validates the last field in the array only.
Here is the function.
function SetErrorFields(fields) {
var ErrorFields = fields;
for (Field in ErrorFields) {
alert("Field: "+ErrorFields[Field][0]+" | Validations: "+ErrorFields[Field][1]);
$('#'+ErrorFields[Field][0]).blur(function(){
Validate(ErrorFields[Field][0],ErrorFields[Field][1]);
});
}
}
I've tried changing a couple of things, but either nothing has worked or things get worse. Bellow is a list of what I tried and the result.
Changed ErrorFields[Field][0] to Field[0], but that changes everything in the alert to "undefined".
Using the following code throws "x is undefined" errors, when leaving the field.
for (x=0; x<ErrorFields.length; x++) {
alert("Field: "+ErrorFields[x][0]+" | Validations: "+ErrorFields[x][1]);
$('#'+ErrorFields[x][0]).blur(function(){
Validate(ErrorFields[x][0],ErrorFields[x][1]);
});
}
And I can't figure out the each method.
There is a useful parameter called eventData. It lets you send data to an event when it's declared. The below works.
function SetErrorFields(fields) {
ErrorFields = fields;
for (Field in ErrorFields) {
alert(ErrorFields[Field][0]+" | "+ErrorFields[Field][1]+" | "+$('#'+ErrorFields[Field][0]).val());
$('#'+ErrorFields[Field][0]).blur({fld: ErrorFields[Field][0], err: ErrorFields[Field][1]}, function(event){
Validate(event.data.fld,event.data.err);
});
}
}
For a more indepth explanation on what it does go here.