Select to view content in your preferred language

Composite parameters: Allow filters

318
2
08-27-2025 07:45 AM
Status: Open
AlfredBaldenweck
MVP Regular Contributor

I'm building a tool that can take either a Field or Linear Unit input for one of the parameters (For an example of what this looks like, see the Buffer Geoprocessing tool).

I'd really like to filter the field version by type, but I get an error when I try.

Please add in the ability to add filters to composite parameters.

2 Comments
HaydenWelch

If I want to do this sort of thing, I'll usually just make two parameters and switch between them. Downside being you now have 3 parameters to manage instead of the one:

from arcpy import Parameter, AddMessage

class Toolbox:
    def __init__(self) -> None:
        self.label = 'Switching Toolbox'
        self.alias = 'SwitchingToolbox'
        self.tools = [ParameterSwitch]

class ParameterSwitch:
    def __init__(self) -> None:
        self.label = 'Parameter Switch'
        
    def getParameterInfo(self) -> list[Parameter]:
        
        features = Parameter(
            name='features',
            parameterType='Required',
            direction='Input',
            datatype='GPFeatureLayer',
        )
        
        switch = Parameter(
            name='switch',
            displayName='Distance [value or field]',
            direction='Input',
            parameterType='Required',
            datatype='GPString',
        )
        if switch.filter:
            switch.filter.list = ['Linear Unit', 'Field']
        switch.value = 'Linear Unit'
        
        unit = Parameter(
            name='unit',
            displayName='',
            direction='Input',
            parameterType='Optional',
            datatype='GPLinearUnit',
        )
        
        field = Parameter(
            name='field',
            displayName='',
            direction='Input',
            parameterType = 'Optional',
            datatype='Field',
        )
        field.parameterDependencies = ['features']
        
        return [features, switch, unit, field]
        
    def updateParameters(self, params: list[Parameter]) -> None:
        _, switch, unit, field = params
        
        match switch.value:
            case 'Linear Unit':
                unit.enabled = True
                field.enabled = False
            case 'Field':
                field.enabled = True
                unit.enabled = False
            case _:
                pass
            
    def execute(self, params: list[Parameter], messages) -> None:
        feat, s, u, field = params
        use_field = s.valueAsText == 'Field'
        
        field = field.value
        unit = u.value
        features = feat.value
        
        if use_field:
            AddMessage(f'Using field {field} for feature class {features.name}')
        else:
            AddMessage(f'Using linear unit ({unit}) for feature class {features.name}')
        
AlfredBaldenweck

I've definitely gone that way before, but why write and manage 2 parameters when you can do one? If you're going to give me the option of a composite parameter, give me the functionality of a normal parameter while you're there.