Enable Uialertaction of Uialertcontroller Only After Input Is Validated

Enable UIAlertAction of UIAlertController only after input is validated

Add following property in your header file

@property(nonatomic, strong)UIAlertAction *okAction;   

then copy the following code in your viewDidLoad method of your ViewController

self.okAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:nil];
self.okAction.enabled = NO;

UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil
message:@"Enter your text"
preferredStyle:UIAlertControllerStyleAlert];

[controller addTextFieldWithConfigurationHandler:^(UITextField *textField) {

textField.delegate = self;
}];

[controller addAction:self.okAction];
[self presentViewController:controller animated:YES completion:nil];

Also implement the following UITextField delegate method in your Class

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{

NSString *finalString = [textField.text stringByReplacingCharactersInRange:range withString:string];
[self.okAction setEnabled:(finalString.length >= 5)];
return YES;
}

This should work

Check on UIAlertController TextField for enabling the button

I would first create the alertcontroller with the save action initially disabled. Then when adding the textfield inculde a Notification to observe its change in the handler and in that selector just toggle the save actions enabled property.

Here is what I am saying:

//hold this reference in your class
weak var AddAlertSaveAction: UIAlertAction?

@IBAction func addTherapy(sender : AnyObject) {

//set up the alertcontroller
let title = NSLocalizedString("New Prescription", comment: "")
let message = NSLocalizedString("Insert a name for this prescription.", comment: "")
let cancelButtonTitle = NSLocalizedString("Cancel", comment: "")
let otherButtonTitle = NSLocalizedString("Save", comment: "")

let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)

// Add the text field with handler
alertController.addTextFieldWithConfigurationHandler { textField in
//listen for changes
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleTextFieldTextDidChangeNotification:", name: UITextFieldTextDidChangeNotification, object: textField)
}

func removeTextFieldObserver() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: alertController.textFields[0])
}

// Create the actions.
let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel) { action in
NSLog("Cancel Button Pressed")
removeTextFieldObserver()
}

let otherAction = UIAlertAction(title: otherButtonTitle, style: .Default) { action in
NSLog("Save Button Pressed")
removeTextFieldObserver()
}

// disable the 'save' button (otherAction) initially
otherAction.enabled = false

// save the other action to toggle the enabled/disabled state when the text changed.
AddAlertSaveAction = otherAction

// Add the actions.
alertController.addAction(cancelAction)
alertController.addAction(otherAction)

presentViewController(alertController, animated: true, completion: nil)
}

//handler
func handleTextFieldTextDidChangeNotification(notification: NSNotification) {
let textField = notification.object as UITextField

// Enforce a minimum length of >= 1 for secure text alerts.
AddAlertSaveAction!.enabled = textField.text.utf16count >= 1
}

I am doing this in another project - I got this pattern directly from apple examples. They have a very good example project outlining a few of these patterns in the UICatalog examples: https://developer.apple.com/library/content/samplecode/UICatalog/Introduction/Intro.html

How do I validate TextFields in an UIAlertController?

This can be done by extending UIAlertViewController:

extension UIAlertController {

func isValidEmail(_ email: String) -> Bool {
return email.characters.count > 0 && NSPredicate(format: "self matches %@", "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,64}").evaluate(with: email)
}

func isValidPassword(_ password: String) -> Bool {
return password.characters.count > 4 && password.rangeOfCharacter(from: .whitespacesAndNewlines) == nil
}

func textDidChangeInLoginAlert() {
if let email = textFields?[0].text,
let password = textFields?[1].text,
let action = actions.last {
action.isEnabled = isValidEmail(email) && isValidPassword(password)
}
}
}

// ViewController
override func viewDidLoad() {
super.viewDidLoad()

let alert = UIAlertController(title: "Please Log In", message: nil, preferredStyle: .alert)

alert.addTextField {
$0.placeholder = "Email"
$0.addTarget(alert, action: #selector(alert.textDidChangeInLoginAlert), for: .editingChanged)
}

alert.addTextField {
$0.placeholder = "Password"
$0.isSecureTextEntry = true
$0.addTarget(alert, action: #selector(alert. textDidChangeInLoginAlert), for: .editingChanged)
}

alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))

let loginAction = UIAlertAction(title: "Submit", style: .default) { [unowned self] _ in
guard let email = alert.textFields?[0].text,
let password = alert.textFields?[1].text
else { return } // Should never happen

// Perform login action
}

loginAction.isEnabled = false
alert.addAction(loginAction)
present(alert, animated: true)
}

Sample Image

how to disable the both uialertcontroller button when no input in uitext field of uialertview controller

Disable the buttons initially and then once you have something in your text field re-enable them.

UIAlertController *alert = [UIAlertController
alertControllerWithTitle:@"Info"
message:@"You are using UIAlertController with Actionsheet and text fields"

preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* ok = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
NSLog(@"Resolving UIAlert Action for tapping OK Button");
[alert dismissViewControllerAnimated:YES completion:nil];

}];
UIAlertAction* cancel = [UIAlertAction
actionWithTitle:@"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
NSLog(@"Resolving UIAlertActionController for tapping cancel button");
[alert dismissViewControllerAnimated:YES completion:nil];

}];
[ok setEnabled:false];

[cancel setEnabled:false];

[alert addAction:ok];
[alert addAction:cancel];

For adding the selector to the text field and then handling it:

[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = @"iCloud ID";
textField.textColor = [UIColor blueColor];
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.borderStyle = UITextBorderStyleRoundedRect;
[textField addTarget:self action:@selector(textDidChange:) forControlEvents:UIControlEventEditingChanged];
}];

- (void)textDidChange:(UITextField *)textField {
if (textField.text.length > 0) {
// enable the buttons
}
}

For handling textfield delegates you can go through the following posts:

  • Access input from UIAlertController
  • Check on UIAlertController TextField for enabling the button

Prevent dismissal of UIAlertController

You're correct: if the user can tap a button in your alert, the alert will be dismissed. So you want to prevent the user from tapping the button! It's all just a matter of disabling your UIAlertAction buttons. If an alert action is disabled, the user can't tap it to dismiss.

To combine this with text field validation, use a text field delegate method or action method (configured in the text field's configuration handler when you create it) to enable/disable the UIAlertActions appropriately depending on what text has (or hasn't) been entered.

Here's an example. We created the text field like this:

alert.addTextFieldWithConfigurationHandler {
(tf:UITextField!) in
tf.addTarget(self, action: "textChanged:", forControlEvents: .EditingChanged)
}

We have a Cancel action and an OK action, and we brought the OK action into the world disabled:

(alert.actions[1] as UIAlertAction).enabled = false

Subsequently, the user can't tap OK unless there is some actual text in the text field:

func textChanged(sender:AnyObject) {
let tf = sender as UITextField
var resp : UIResponder = tf
while !(resp is UIAlertController) { resp = resp.nextResponder() }
let alert = resp as UIAlertController
(alert.actions[1] as UIAlertAction).enabled = (tf.text != "")
}

EDIT Here's the current (Swift 3.0.1 and later) version of the above code:

alert.addTextField { tf in
tf.addTarget(self, action: #selector(self.textChanged), for: .editingChanged)
}

and

alert.actions[1].isEnabled = false

and

@objc func textChanged(_ sender: Any) {
let tf = sender as! UITextField
var resp : UIResponder! = tf
while !(resp is UIAlertController) { resp = resp.next }
let alert = resp as! UIAlertController
alert.actions[1].isEnabled = (tf.text != "")
}

shouldChangeCharactersInRange is not getting called

phoneNumberTF is not a part of UIAlertController so no need of delegate for this phoneNumberTF.delegate = self;

add the configuration delegate to your UIAlertController

 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Enter your phone number" message:nil preferredStyle:UIAlertControllerStyleAlert];

[alert addTextFieldWithConfigurationHandler:^(UITextField *textField)
{

textField.delegate = self;
}];

for more info you get the sample here

How do you disable a UIAlertAction depending on a UITextField in a UIAlertController?

Implement the logic in the shouldChangeCharactersIn delegate method of UITextField. This method gets fired on change in each character of textfield.
You can build the logic taking the range parameter into consideration.

Here is the code that works perfectly.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

if ((range.location == 4 && range.length == 0) || (range.location == 5 && range.length == 1)) {
self.alertController.actions[0].isEnabled = true
}else{
self.alertController.actions[0].isEnabled = false
}

return true;
}

Tested successfully in Swift 3, XCode 8 and iOS 10

Hope that helps.
Happy coding ...

How to enable/disable Alert action?

Do this

textField.addTarget(self, action: #selector(self.textEdited), for: .editingChanged)

@objc func textEdited(_ textField:UITextField) {

if textField.text!.count > 0 {
alert.actions.first?.isEnabled = true
}else{
alert.actions.first?.isEnabled = false
}

}

Add this line that will disable it initially

 alert.actions.first?.isEnabled = false
self.present(alert, animated: true)


Related Topics



Leave a reply



Submit