Search code examples
cocoacocoa-bindingsnspopupbutton

Tiered NSPopupButton binding


I'm trying to have two NSPopupButton that are linked to each other and am having issues with the bindings on the 'child' button.

I have three Core Data entity types: Order, Client, and Station. Station -> Client is a many-to-1, so a Client has multiple Station, but a Station can only point to one client.

An Order has a single Station attached to it, so I created all the bindings like I show below. I can properly pick any client from the first dropdown, but then the stations dropdown just shows the currently selected station. I don't see all the stations available, and if I change the client, I don't see a new list of stations to choose from.

Order Controller

An NSObjectController bound to the order entity property in the view controller.

Clients Array Controller

Just binds to the view controller's managedObjectContext to get all clients.

Stations Array Controller

enter image description here enter image description here

Client NSPopupButton

Content Binding Content Values Binding Selected Index Binding

Station NSPopupButton

Station Dropdown Content Binding Station Dropdown Content Values Binding Station Dropdown Selected Object Binding


Solution

  • The selected value of the client popup button is used to filter the stations, it shouldn't change the client of the station of the order. Bind Selected index (instead of Selected Object) of the client popup button to the Client Array Controller, Controller Key selectionIndex, no Model Key Path.

    Bind Selected Object of the station popup button to the Order Object Controller, Controller Key selection, Model Key Path station.

    When the user selects a client, the selected station is still the station of the order. If this station has a different client, the station popup button doesn't automagically select another station. You can fix this in the action of the client popup button. For example:

    - (IBAction)clientAction:(id)sender {
        NSArray *stations = self.stationArrayController.arrangedObjects;
        if (![stations containsObject:order.station]) {
            if (stations.count > 0)
                self.order.station = stations[0];
            else
                self.order.station = nil;
        }
    }