Advent of Code is back! Unwrap daily challenges to sharpen your Alteryx skills and earn badges along the way! Learn more now.

Alteryx Designer Desktop Discussions

Find answers, ask questions, and share expertise about Alteryx Designer Desktop and Intelligence Suite.
SOLVED

How to persist tool input values in Python SDK v2/UI SDK?

computergeek
5 - Atom

I'm creating a custom tool using Python SDK v2 and UI SDK.  Per the getting started guide, I installed all the prerequisites and used ayx_plugin_cli to create a new project template.

 

I modified my index.tsx file to add several TextFields:

return (
    <Box p={4}>
     <Grid container spacing={4} direction="column" alignItems="center">
        <Grid item>
          <Alteryx className={classes.alteryx} />
        </Grid>
        <Grid item>
          <TextField name='system' label="System" placeholder='System' value={"my_system"}/>
        </Grid>
        <Grid item>
          <TextField name='username' label="Username" placeholder='Username'/>
        </Grid>
        <Grid item>
          <TextField name='password' label="Password" placeholder='Password' type='password'/>
        </Grid>

        <Grid item>
          <TextField name='sql' label="SQL Statement" multiline></TextField>
        </Grid>
      </Grid>
    </Box>
  )
}
 
I'm accessing values on the Python side in the on_complete event like so:
 
        system = self.provider.tool_config.get('system')
        username = self.provider.tool_config.get('username')
        password = self.provider.tool_config.get('password')
        sql = self.provider.tool_config.get('sql')
 
When I install my plugin, I can see the new fields in my tool configuration, but when I exit the tool and click back into it, the values I typed in are not saved.
 
None of the examples appear to show how to persist the values.
 
Thanks in advance for any assistance.
 
1 REPLY 1
computergeek
5 - Atom

There's no quicker way for me to figure something out myself, than to ask a question.

 

I figured it out.  In the files that are generated by ayx_plugin_cli, there's a folder: ui/<your tool name>/src/tool-templates.  In those files, it shows how the tool data can be persisted.

 

For others' sake, here's my whole index.tsx file:

 

import React, { useContext, useEffect} from 'react';
import ReactDOM from 'react-dom';
import { AyxAppWrapper, Box, Grid, Typography, makeStyles, Theme } from '@alteryx/ui';
import { Alteryx } from '@alteryx/icons';
import { Context as UiSdkContext, DesignerApi } from '@alteryx/react-comms';
import { TextField } from '@alteryx/ui';


const useStyles = makeStyles((theme: Theme) => ({
  alteryx: {
    color: theme.palette.brand.corporateBlue,
    height: '125px',
    width: '125px'
  }
}));

const App = () => {
  const classes = useStyles();
  const [model, handleUpdateModel] = useContext(UiSdkContext);


  // Dev Harness Specific Code ---------- Start
  // The following code is specifically a dev harness functionality.
  // If you're developing a tool for Designer, you'll want to remove this
  // and check out our docs for guidance 
  useEffect(() => {
    handleUpdateModel(model)
  }, []);
  // Dev Harness Specific Code ---------- End

  const onHandleTextChange = event => {
    const newModel = { ...model };
    newModel.Configuration[event.target.name] = event.target.value;
    handleUpdateModel(newModel);
  };

  return (
    <Box p={4}>
     <Grid container spacing={4} direction="column" alignItems="center">
        <Grid item>
          <Alteryx className={classes.alteryx} />
        </Grid>
        <Grid item>
          <TextField name='system' label="System"
            placeholder='System' 
            onChange={onHandleTextChange}
            value={model.Configuration.system || "" } />
        </Grid>
        <Grid item>
          <TextField name='username' label="Username" placeholder='Username'
            onChange={onHandleTextChange}
            value={model.Configuration.username || "" } />
        </Grid>
        <Grid item>
          <TextField name='password' label="Password" placeholder='Password' type='password' 
            onChange={onHandleTextChange}
            value={model.Configuration.password || "" } />
        </Grid>
        <Grid item>
          <TextField name='sql' label="SQL Statement" 
            onChange={onHandleTextChange}
            value={model.Configuration.sql || ""} multiline></TextField>
        </Grid>
      </Grid>
    </Box>
  )
}

const Tool = () => {
  return (
    <DesignerApi messages={{}}>
      <AyxAppWrapper> 
        <App />
      </AyxAppWrapper>
    </DesignerApi>
  )
}

ReactDOM.render(
  <Tool />,
  document.getElementById('app')
);

 

The notable parts are here:

  const onHandleTextChange = event => {
    const newModel = { ...model };
    newModel.Configuration[event.target.name] = event.target.value;
    handleUpdateModel(newModel);
  };

This code creates a copy of the model dictionary and updates its Configuration object with the new value.  Then it tells Alteryx to replace the old model with the new model.

 

 

        <Grid item>
          <TextField name='username' label="Username" placeholder='Username'
            onChange={onHandleTextChange}
            value={model.Configuration.username || "" } />
        </Grid>

In the TextField, we added a name, onChange event, and value.  The onChange event calls the code above when the TextField changes, and the value field fills in the value of the TextField when the model is initialized (i.e. the user configures the tool).

 

Note we also added an import statement at the top, so we can use the TextField tag in our UI:

 

import { TextField } from '@alteryx/ui';
Labels