Alteryx IO Discussions

Customize and extend the power of Alteryx with SDKs, APIs, custom tools, and more.

Platform SDK UI defaultConfig not loading

rcalderon
5 - Atom

Hello

 

I'm trying out the new Platform SDK and I'm having trouble with the UI's default configuration. According to the docs in https://alteryx.github.io/react-comms/#/Designer%20Api/Usage you can setup the defaultConfig prop in the DesignerApi component for consistency on tool initialization. However, when I test my tool (both in Dev Harnes and in Designer) it is not until after I interact with the UI that the values for the UI components are set, before that it is as if they were non existent.

 

Before interacting with the UI:

rcalderon_0-1650596963646.png

 

After interacting with the UI:

rcalderon_1-1650597043747.png

 

This causes an error during initialization('Could not init plugin KeyError') if I try to access the config values in the backend without having interacted with the UI. It is not really a big deal since I can always interact with the UI without changing the default values and the tool updates correctly but I wonder if there's a way around this.

 

Any help would be appreciated!

 

P.S. Here is the snippet where I declare the defaultConfig.

 

const Tool = () => {

  return (
    <DesignerApi messages={{}} defaultConfig={{ Configuration: { numRecords: 0, doSort: false, orderType: 'desc', fieldSelect: ''  } }}>
      <AyxAppWrapper>
        <App />
      </AyxAppWrapper>
    </DesignerApi>
  )
}
7 REPLIES 7
Aguisande
15 - Aurora
15 - Aurora

Sorry, my bad.

Aguisande
15 - Aurora
15 - Aurora

Maybe @jarrod  or  @CassC can help with this?

jarrod
ACE Emeritus
ACE Emeritus

hey @rcalderon,

 

After setting the default value in the "const Tool" section, you'll need to set the element's defaultValue to {model.Configuration.elementKeyThatYouDefined}

 

in my case, it was:

defaultValue = {model.Configuration.fieldSelect}

 

However, I'm actually having the opposite issue on my end. (my values disappear from the tool after i select off then back on). Do your values persist after clicking on the canvas then selecting the tool again? The only way i was able to hack that a bit was to display the values as a placeholder using the defaultValue logic as above. I would be interested to know if you solved that one. Thanks!

rcalderon
5 - Atom

Thanks @jarrod

 

Unfortunately the defaultConfig is still not loading even after I set the element's defaultValue, but I think it is because of the way Designer loads any tool's config, not only ones created with the SDK. I came to that conclusion after checking with the XML viewer how and when does Alteryx sets the config for an Input tool and it is the same as with the tool I created (config doesn't exist until after I interact with the UI). However, what I wanted with my tool was to define a way for the tool to act even if the user didn't interact with the UI, so what I did was to setup that logic in the backend with a try/except clause.

 

In regards of your issue, in my case the actual values do persist when I click on the canvas and then the tool, but the interface sometimes changes. My interface has a TextField and below that a CheckBox which displays a DropDown and a RadioGroup when selected. When the CheckBox is selected everything persists correctly; but when it is not, when I click on the canvas and then the tool the CheckBox appears as selected and the other elements are present in the interface, although the actual config values remain the same and the workflow runs with the correct config values.

jarrod
ACE Emeritus
ACE Emeritus

@rcalderon would you be able to share the tsx file here? or DM me and we can trade notes. I was able to get the values to show up again after re-clicking the tool but I need to test it further to make sure it's sticking. 

rcalderon
5 - Atom

The portal doesn't allow sharing tsx files but here is the full code.

 

I think I just figured out what is happening, I just need to fix it now. The doSort parameter is changing from boolean to string somewhere and that is messing with the logic of the interface.

 

import React, { useContext } from 'react';
import ReactDOM from 'react-dom';
import {
  AyxAppWrapper,
  Box,
  Autocomplete,
  Grid,
  Checkbox,
  FormControl,
  FormControlLabel,
  InputLabel,
  TextField,
  RadioGroup,
  Radio
} from '@alteryx/ui';
import { Context as UiSdkContext, DesignerApi } from '@alteryx/react-comms';

const App = () => {
  const [model, handleUpdateModel] = useContext(UiSdkContext);
  const generateData = data => {
    return data.map(item => {
      item.primary = item.name;
      item.value = item.name;
      item.label=item.name;
      return item;
    });
  };

  const handleNumChange = (e) => {
    const newModel = { ...model };
    newModel.Configuration.numRecords = e.target.value;
    handleUpdateModel(newModel);
  }

  const handleSortChecked = (e) => {
    const newModel = { ...model };
    newModel.Configuration.doSort = e.target.checked;
    handleUpdateModel(newModel);
    console.log(model.Configuration.doSort)
  }

  const handleOrderChange = (e) => {
    const newModel = { ...model };
    newModel.Configuration.orderType = e.target.value;
    handleUpdateModel(newModel);
  }

  const handleFieldSelect = (e,val) => {
    const newModel = { ...model };
    newModel.Configuration.fieldSelect = val.name;
    handleUpdateModel(newModel);
    console.log(model.Configuration.fieldSelect)
  }

  return (
    <Box p={4}>
      <Grid container>
        <Grid item md={3} sm={6} xs={12}>
          <FormControl>
            <InputLabel htmlFor="numRecords">Select the number of records:</InputLabel>
            <TextField type="number" id="numRecords" onChange={handleNumChange} value={model.Configuration.numRecords} defaultValue={model.Configuration.numRecords}/>
            <Box marginTop={2}>
              <FormControlLabel
                control={
                  <Checkbox
                    checked={model.Configuration.doSort}
                    color="primary"
                    onChange={handleSortChecked}
                    value={model.Configuration.doSort}
                    defaultValue={model.Configuration.doSort}
                  />
                }
                label="Sort Incoming Data (Optional)"
              />
            </Box>
            {
                model.Configuration.doSort ?
                <Box p={2}>
                  <InputLabel htmlFor="select">Select a field to order by:</InputLabel>
                  <Autocomplete
                    id="Autocomplete"
                    options={generateData(model.Meta?.fields[0][0].fields)}
                    getOptionLabel= {(option) => option.value ?? option}
                    getOptionSelected={(option, value) => option === value}
                    renderInput={(params) => (
                      <TextField
                        {...params}
                        fullWidth
                        id="ac-meta"
                        label="Meta Data"
                        margin="normal"
                        placeholder="Select Column..."
                      />
                    )}
                    onChange={handleFieldSelect}
                    value={model.Configuration.fieldSelect}
                    defaultValue={model.Configuration.fieldSelect}
                  />
                  <Box marginTop={2}>
                    <InputLabel htmlFor="radio">Select the order:</InputLabel>
                    <RadioGroup aria-label="Gender" name="gender1" onChange={handleOrderChange} value={model.Configuration.orderType} defaultValue={model.Configuration.orderType}>
                      <FormControlLabel control={<Radio />} label="Descending" value="desc" />
                      <FormControlLabel control={<Radio />} label="Ascending" value="asc" />
                    </RadioGroup>
                  </Box>
                </Box>
              : <Box p={2}></Box>
            }
          </FormControl>
        </Grid>
      </Grid>
    </Box>
  )
}

const Tool = () => {

  return (
    <DesignerApi messages={{}} defaultConfig={{ Configuration: { numRecords: 0, doSort: false, orderType: 'desc', fieldSelect: ''  } }}>
      <AyxAppWrapper>
        <App />
      </AyxAppWrapper>
    </DesignerApi>
  )
}

ReactDOM.render(
  <Tool />,
  document.getElementById('app')
);
mkhtran
9 - Comet

One workaround for this issue is to add a useEffect hook that sets the configuration on the initial load.

 

const App = (): JSX.Element => {
  const [model, handleUpdateModel] = useContext(UiSdkContext)

  // Force a save of the initial configuration
  useEffect(() => {
    handleUpdateModel({ ...model })
  }, [])

  return (
    /* ... */
  )
}