0

I am new in SwiftUi and I am trying to show Alert message with TextField and action button, I want to use Alert function for this, but I can't add TextField in Alert function,I shared code at below, how can I add TextField in Alert function? thanks..

.alert(isPresented:$showAlertDialog) {                                            
    Alert(
          title: Text("Please Enter sended E-mail Code"),
          message: Text("There is no undo"),
          primaryButton: .destructive(Text("Submit")) {
          print("Deleting...")
          },
          secondaryButton: .cancel()
          )
          }
Diego
  • 937
  • 8
  • 24

2 Answers2

3

As of iOS 15 alerts are not capable of showing TextFields. But you can make a custom SwiftUI alert.

struct TextFieldAlert: ViewModifier {
    @Binding var isPresented: Bool
    let title: String
    @Binding var text: String
    let placeholder: String
    let action: (String) -> Void
    func body(content: Content) -> some View {
        ZStack(alignment: .center) {
            content
                .disabled(isPresented)
            if isPresented {
                VStack {
                    Text(title).font(.headline).padding()
                    TextField(placeholder, text: $text).textFieldStyle(.roundedBorder).padding()
                    Divider()
                    HStack{
                        Spacer()
                        Button(role: .cancel) {
                            withAnimation {
                                isPresented.toggle()
                            }
                        } label: {
                            Text("Cancel")
                        }
                        Spacer()
                        Divider()
                        Spacer()
                        Button() {
                            action(text)
                            withAnimation {
                                isPresented.toggle()
                            }
                        } label: {
                            Text("Done")
                        }
                        Spacer()
                    }
                }
                .background(.background)
                .frame(width: 300, height: 200)
                .cornerRadius(20)
                .overlay {
                    RoundedRectangle(cornerRadius: 20)
                        .stroke(.quaternary, lineWidth: 1)
                }
            }
        }
    }
}

extension View {
    public func textFieldAlert(
        isPresented: Binding<Bool>,
        title: String,
        text: Binding<String>,
        placeholder: String = "",
        action: @escaping (String) -> Void
    ) -> some View {
        self.modifier(TextFieldAlert(isPresented: isPresented, title: title, text: text, placeholder: placeholder, action: action))
    }
}

Use it on the root view. (don't attach it to Buttons to other inner elements for example). This will ensure that presenting view is disabled. Sample usage:

struct ContentView: View {
    @State var isAlertDisplayed = false
    @State var text = "Text to change"
    
    var body: some View {
        VStack {
            Text("Press the button to show the alert").multilineTextAlignment(.center)
            Text("Current value is: \(text)")
            Button("Change value") {
                withAnimation {
                    isAlertDisplayed = true
                }
            }
            .padding()
        }
        .textFieldAlert(isPresented: $isAlertDisplayed, title: "Some title", text: $text, placeholder: "Placeholder", action: { text in
            print(text)
        })
        .padding()
    }
}
Paul B
  • 3,989
  • 33
  • 46
1

I think you actually can - maybe it came back in iOS 16. This verified to work for me:

.alert("Alert message...", isPresented: $isShowingAlert) {
    TextField("", text: $alertInput)
    Button("OK", action: {})
}
Oded Ben Dov
  • 9,936
  • 6
  • 38
  • 53
  • Yes, this does work in iOS16 and yes, it does'n work in iOS15 (as of Xcode14). That is the reason why I'm upvoting this answer a useful one. Are you sure this is also the reason for downvoting my answer? – Paul B Aug 13 '23 at 10:41
  • 1
    You wrote "As of iOS15", and since it's working on 16, I didn't want people reading the answer and taking the wrong impression. No offense meant – Oded Ben Dov Aug 13 '23 at 10:44
  • Some folks will be dropping iOS15 in years from the time of writing. – Paul B Aug 13 '23 at 13:46