0

I am doing my first Swift UI project. I am having a form backed by a view-model (vm: SectionFormViewModel). I found a neat solution to limit inputs to numbers in this SO answer.

struct SectionForm: View {

    // @ObservedObject var homeVM: HomeViewModel

    @StateObject var vm = SectionFormViewModel()

    var body: some View {
        // ....
    }

    var roomVolume: some View {
        Section(header: Text("Room Dimensions")) {
            if vm.manualArea {
                HStack {

                    // Required to extract to component
                    // --------------------------------

                    TextField("Length (feet)", text: $vm.length)
                        //.keyboardType(.numberPad)
                        .onReceive(Just(vm.length)) { newValue in
                            let filtered = newValue.filter { "0123456789".contains($0) }
                            if filtered != newValue {
                                vm.length = filtered
                            }
                        }

My idea was to create my own NumberField. It would be called like this:

NumberField(label: "Length (feet)", binding: $vm.length)

But I can't figure out exactly how.

struct NumberField: View {
    @Binding var binding: Binding<String>
    
    var body: some View {
        TextField("Length (feet)", text: binding)
            //.keyboardType(.numberPad)
            .onReceive(Just($binding.wrappedValue)) { newValue in
                let filtered = newValue.filter { "0123456789".contains($0) }
                if filtered != newValue {
                    $binding.length = filtered
                }
            }
    }
}

First of all, is it possible to do something like that?

I don't think it can be @State because it is defined elsewhere. I think it should be a @Binding. It might be an obvious thing, but after many searches, hours of teeth grinding, nail biting and hairline receding, I am confident I need some help.

Sorry about the title, I am not even sure how to word it. I am that new to Swift!

1 Answer 1

2

The problem is, you have created binding of binding. which is wrong. see your code. Two bindings are there.

 @Binding var binding: Binding<String>

Your building should be like this.

struct NumberField: View {
    var label: String
    @Binding var binding: String
    
    var body: some View {
        TextField("Length (feet)", text: $binding)
            //.keyboardType(.numberPad)
            .onReceive(Just(binding)) { newValue in
                let filtered = newValue.filter { "0123456789".contains($0) }
                if filtered != newValue {
                    binding = filtered
                }
            }
    }
}

Now you can use it like this

NumberField(label: "Length (feet)", binding: $vm.length)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.