ReactiveCocoa - observing isFirstResponder property and UITextField with clearsOnBeginEditing set to YES - validation

I am new to ReactiveCocoa, but I think it's very nice and outstanding technique for reducing code complexity. I just started experiencing with the framework, and not everything is clear for me at the moment, so excuse me if my problem can be solved in some obvious way.
In my app I have login view controller with simple form contains two text fields (username and password) and a button. I would like the button to be disabled if any of two text fields is empty. So, I wrote this code:
RAC(self.loginButton, enabled) =
[RACSignal combineLatest:#[self.userTextField.rac_textSignal,
self.passwordTextField.rac_textSignal]
reduce:^(NSString *username,
NSString *password) {
BOOL valid = (username.length > 0 && password.length > 0);
return #(valid);
}];
It's very simple and it's working. The problem is that one of my text fields (the password field) has secureTextEntry and clearsOnBeginEditing properties set to YES. I will try to explain unwanted behavior that I am experiencing with this configuration:
Let's assume that both username and password fields are NOT empty. In this case the button is enabled. When user taps on password field, it becomes first responder (keyboard appears and user can enter his password), but because of clearsOnBeginEditing being set to YES for that field, the previously entered password is cleared from the text field. That's way password field is now empty. The problem is that signal is not being sent, so the button remains enabled, despite the password field is empty.
My first idea to solve this issue (well, more like workaround solution) was to observe isFirstResponder property on password field beside observing text changes. That's way the block that checks if button should be enabled would be called when password field becomes first responder. I don't know if this solution works, because I have no idea how to implement it using ReactiveCocoa. I have looking for creating a signal for isFirstResponder property changes, but without a luck. It might be not the best approach in order to solve this issue, but nothing comes to my mind at this point.
Then, the question is: how to observe isFirstResponder property with ReactiveCocoa?
And more general question: how to observe text field's text changes when clearsOnBeginEditing is set to YES?
UPDATE:
I found out that I can create signal for UIControlEventEditingDidBegin event that should give me substitution of observing isFirstResponder property changes:
[self.passwordTextField rac_signalForControlEvents:UIControlEventEditingDidBegin]
Unfortunately this does not solve the issue. Now I understand that field is cleared AFTER it becomes first responder, and clearing field automatically after it becomes first responder does not send signal for text changes. That's way when validation block is executed it still thinks that password field is not empty, and the button remains enabled despite password field was cleared and it's empty.

Unfortunately the -rac_textSignal only listens for UIControlEventEditingChanged. If UIControlEventEditingDidBegin were added, you'd be all set.
I suppose you could patch this into it and submit a pull request?
- (RACSignal *)rac_textSignal {
#weakify(self);
return [[[[[RACSignal
defer:^{
#strongify(self);
return [RACSignal return:self];
}]
concat:[self rac_signalForControlEvents:UIControlEventEditingChanged|UIControlEventEditingDidBegin]]
map:^(UITextField *x) {
return x.text;
}]
takeUntil:self.rac_willDeallocSignal]
setNameWithFormat:#"%# -rac_textSignal", [self rac_description]];
}

Related

How can i force validation on the initial values in a formik form, when it mounts

I am in React 16+, using withFormik for the form.
Its a single field form which on initial use will have an empty string value. I want the initial value to be validated so the user knows they must fill a value.
So blank string "" initial value, i want the error to say "please enter a value" without the user touching or anything. onload.
formik docs claim it can do this thru the built in tools, but the library/docs dont add up.
validateOnMount:
https://formik.org/docs/api/withFormik#validateonmount-boolean
this value does nothing when set to true in my form. There are lots of logged issues of others having the same problems. It seems formik depreciated an old property that used to do this well. i cant find anything to do this without building some type of hack.
how can i have formik run the validation as ssoon as the from mounts.
in case your answer is to disable the "enableReinitialize" property, ive tried this in conjunction with validateOnMount: true and still get nothing.

How do you place default message in the semantic react ui search?

https://react.semantic-ui.com/modules/search
Below is images of how the semantic react ui search widget looks like. In the second image, I was wondering how you can put a prompt message to indicate to the user a message on what the search bar is meant for. In this case, it's "search". When the user types in, it erases the Search and starts reflecting what the user is typing. I thought it would be defaultValue, but it seems that you can't have value and defaultValue set at the same time. I still want to be able to read what the set value is when the user types into the box.
Thanks,
Derek
You can use defaultValue as initial value in component, no problem.
Then read the user input value in event (onBlur for instance) like this:
onBlur(e) {
e.preventDefault();
console.log(e.target.name, e.target.value);
}
If you want to read value each new character pressed you can use in onSearchChange event:
onSearchChange(e) {
e.preventDefault();
console.log(e.target.name, e.target.value);
}
EDIT: included accepted answer in comment below:
Worked:
placeholder={"text"}
for Semantic React UI Search

TouchID: What's the difference between fallback (enter password) and cancel?

I'm integrating TouchID into my app, but I don't get the difference between the two buttons enter password and cancel. They result in an error of LAErrorUserCancel or LAErrorUserFallback, but I can't handle them differently, so I'd like to avoid one of the two buttons. Is there a way to do this? Or what's the best practice here?
1Password is an example here; both buttons the user gets presented are leading to the same action - that you have to enter the password into the app manually. In my opinion it would make sense to have only one button here.
It is super easy to remove the "Enter Password" button if you don't need it for your application. Just set the localizedFallbackTitle property to an empty string, not nil, and the button will not be display.
LAContext *context = [[LAContext alloc] init];
context.localizedFallbackTitle = #"";
(You can't also set it to something more appropriate for your application if you need to, just put the string in there.)
Note: to actually answer the question as posted, not to answer the comment that that OP left on the other answer... the fallback case is useful when the user has decided to not use TouchID but would rather enter a password to gain access to your locked service. You would test for this in the evaluatePolicy message.
If the touchID alert view is displayed from the same VC that contains the password field, both options would accomplish the same. But think in cases where you have workflow where you can cancel the full authentication operation (LAErrorUserCancel) or display a login view controller(LAErrorUserFallback).

How can I validate my Firefox extension's preferences?

What is a generally accepted way to validate preference values in a Firefox extension, specifically when using the prefwindow mechanism in XUL?
I am introducing some new preferences in one of my extensions that I would like to validate before the preferences window is closed. If there's an error, the user should be allowed to correct the issue, and then proceed. I see that the prefwindow element has two potentially useful functions to help in this regard:
onbeforeaccept
ondialogaccept
The former seems to have an associated bug (Bug 474527) that prevents the prefwindow from remaining open when returning false from that function. This is bad in that it doesn't give the user an opportunity to immediately correct their mistake.
The latter appears to have the problem that the preferences get saved prior to exiting, which leaves the preferences in a bad state internally.
In addition, the prefwindow mechanism supports the browser.preferences.instantApply option, in which preference values are written immediately upon updating the associated control. This makes validation extra tricky. Is there a clean way to validate custom preferences in a Firefox extension, allowing the user to correct any potential mistakes?
Normally you would want to validate the preferences when they are changed. That's something that onchange attribute (and the corresponding change event) is good for:
<preference name="preference.name" onchange="validate(this);"/>
The event is fired after the preference value changes. There are two drawbacks:
In case of instantApply the new preference value is already saved, too late to validate and decline.
For text fields the preferences are saved every time a new character is typed. This becomes ugly if you report validation failure while the user is still typing.
You can solve the first issue by intercepting the change events for the actual input fields. For example, for a text field you would do:
<input preference="preference.name"
oninput="if (!validate(this)) event.stopPropagation();"
onchange="if (!validate(this)) { event.stopPropagation(); this.focus(); }"/>
So changes that don't validate correctly don't bubble up to the <prefpane> element and don't get saved. The events to listen to are: input and change for text fields, command for buttons and checkboxes, select for the <colorpicker> element.
The second issue is tricky. You still want to validate the input when it happens, showing the message immediately would be bad UI however. I think that the best solution is to assume for each input field initially that it is still "in progress". You would only set a flag that the value is complete when you first see a blur event on the field. That's when you can show a validation message if necessary (ideally red text showing up in your preference page, not a modal prompt).
So to indicate what the final solution might look like (untested code but I used something like that in the past):
<description id="error" hidden="true">Invalid preference value</description>
<input preference="preference.name"
_errorText="error"
onblur="validate(event);"
oninput="validate(event);"
onchange="validate(event);/>
<script>
function validate(event)
{
// Perform actual validation
var field = event.target;
var valid = isValid(field);
// If this is the blur event then the element is no longer "in progress"
if (event.type == "blur")
{
field._inputDone = true;
if (!valid)
field.focus();
}
// Prevent preferences changing to invalid value
if (!valid)
event.stopPropagation();
// Show or hide error text
var errorText = document.getElementById(field.getAttribute("_errorText"));
errorText.hidden = valid || !field._inputDone;
}
</script>
If you want to validate values as soon as the field is changed so you can handle the instantApply case, you could hook into the change events for the individual fields (e.g. oninput for a textbox). Display an error message and force the focus back to the field if the value is invalid. You can either set it back to a valid value automatically or block the user from closing the dialog until it is fixed.

Cocoa-Bindings : Update NSObjectController manually?

In my little cocoa application I have bound the properties of a class to some text fields with help of a NSObjectController. The only problem I have so far: you always have to leave a text field before the NSObjectController updates the class with the current input.
This becomes a problem if the user doesn't leave a texfield and clicks on a Save/Submit Button right away. The class doesn't contain the current input. Always a bad thing.
I am looking for a way to avoid this. Like telling the NSObjectController to get the current input even if the user had exited the field. If this is possible I could put this command in the save-Method before saving and all would be fine.
Send a commitEditing message to your controller in the handler for the OK button. This will do what you're asking for. It's as simple as:
- (void)save:sender {
if (![self.myObjectController commitEditing]) {
// Handle error when object controller can't commit editing
}
// Other stuff
}
If you go to the text field's value binding and check the "Continuously Updates Value" option, that will cause the new value to be set on the model object each time the user changes it, i.e. once for each keystroke. That would ensure that the model had the correct value before closing the window, though it may be a bit overkill, depending on what the effects (if any) are of the value being set in your data model.

Resources