Get changes on button tapped using Combine and SwiftUI

321 views Asked by At

Trying to change isValid after the user have chose from the Menu the right position.

It seems to work if I first choose a position and then typing the email and name at the textfields but not the other side.

I want to enable the Button when he chose position and fulfilled the other textfields.

class EmployeeModel: ObservableObject{
    
    @Published var employee: Employee
    @Published var isValid = false
    
    private var cancellables = Set<AnyCancellable>()
    
    init(employee: Employee = Employee(uid: "", affiliate: 0, employeeID: 1, email: "", name: "", shiftsConstIsApplied: false, position: nil, shiftConsts: nil, pushId: "")){
        
        self.employee = employee
        
        self.$employee
            .debounce(for: 0.5, scheduler: RunLoop.main)
            
            .map({!$0.name.isEmpty && !$0.email.isEmpty && $0.position != nil})
            .sink{ input in
                print(input)
                self.isValid = input
            }
            .store(in: &cancellables)
    }
}

The view:


@State private var position: Positions?
@StateObject var employeeModel = EmployeeModel()

Menu(LocalizedStringKey(self.$position.wrappedValue?.rawValue ?? "Choose position")) {
                        ForEach(Positions.employeeTypes, id:\.self){ p in
                            Button(LocalizedStringKey(p)){
                                let positionSelected = Positions(rawValue: p)
                                self.position = positionSelected
                                self.employeeModel.employee.position = positionSelected
                            }
                        }
                    }

Button("Confirm"){
//do something
}
.disabled(!self.employeeModel.isValid)

Model Employee as ObservableObject:

    @Published var uid: String?
    @Published var email: String
    @Published var name: String
    @Published var affiliate: Int?
    @Published var employeeId: Int?
    @Published var shiftsConstIsApplied: Bool? = true
    @Published var position: Positions?
    @Published var shiftConsts: [ShiftConst]?
1

There are 1 answers

1
Asperi On

If I correctly understood your code try the following (not tested!)

init(employee: Employee = Employee(uid: "", affiliate: 0, employeeID: 1, email: "", name: "", shiftsConstIsApplied: false, position: nil, shiftConsts: nil, pushId: "")){
    
    self.employee = employee
    
    self.employee.objectWillChange               // << here !!
        .debounce(for: 0.5, scheduler: RunLoop.main)

, you don't change employee itself (because it is reference type), but just its internal property, so you need to subscribe to its internal publisher.