crsnstack
crsnstack

Reputation: 31

How can I pass a closure into ViewModifier button?

Not sure how to add an optional action to TextFieldButton view and have the TextFieldClearButton view modifier accept the action.

struct TextFieldClearButton: ViewModifier {
    @Binding var fieldText: String
    var action: (() -> Void)? = nil

    func body(content: Content) -> some View {
        content
            .overlay {
                if !fieldText.isEmpty {
                    HStack {
                        Spacer()
                        Button {
                            fieldText = ""
                            action
                        } label: {
                            Image(systemName: "multiply.circle.fill")
                        }
                        .foregroundColor(.secondary)
                        .padding(.trailing, 4)
                    }
                }
            }
    }
}

extension View {
    func showClearButton(_ text: Binding<String>) -> some View {
        self.modifier(TextFieldClearButton(fieldText: text))
    }
}

struct TextFieldButton: View {

    @State private var text = ""
    @FocusState private var isTextFieldFocused: Bool

    var body: some View {
        VStack {
            TextField("", text: $text)
                .textFieldStyle(.roundedBorder)
                .focused($isTextFieldFocused)
                .showClearButton($text)
        }
        .padding()
        .background(Color.purple)
    }
}

So far I can only get an "Expression of type '(() -> Void)?' is unused" warning and I am not sure how or if this needs to passed in as a @Binding.

Upvotes: 0

Views: 406

Answers (2)

crsnstack
crsnstack

Reputation: 31

Here is the full working version of this code:

    @Binding var fieldText: String
    var action: (() -> Void)? = nil

    func body(content: Content) -> some View {
        content
            .overlay {
                if !fieldText.isEmpty {
                    HStack {
                        Spacer()
                        Button {
                            fieldText = ""
                            action?()
                        } label: {
                            Image(systemName: "multiply.circle.fill")
                        }
                        .foregroundColor(.secondary)
                        .padding(.trailing, 4)
                    }
                }
            }
    }
}

extension View {
    func showClearButton(_ text: Binding<String>, action: (() -> Void)? = nil) -> some View {
        self.modifier(TextFieldClearButton(fieldText: text, action: action))
    }
}

struct TextFieldButton: View {

    @State private var text = ""
    @FocusState private var isTextFieldFocused: Bool

    var body: some View {
        VStack {
            TextField("", text: $text)
                .textFieldStyle(.roundedBorder)
                .focused($isTextFieldFocused)
                .showClearButton($text, action: testPrint)
        }
        .padding()
        .background(Color.purple)
    }
    func testPrint() {
        print("Test Print Successful.")
    }
}

Upvotes: 1

whiteio
whiteio

Reputation: 231

action is a property of type (() -> Void)? You need to call the action closure, you can do this by changing it from action to action?()

Button {
    fieldText = ""
    action?()
} label: {
    Image(systemName: "multiply.circle.fill")
}

Upvotes: 0

Related Questions