Auto-Populate Fields

default discord avatar
peniswafflexd2 years ago
1 1

I am currently building a personal blog using Payload and, honestly, it's been an enjoyable process. The config structure is clean and easily understandable, and the documentation is fantastic.

However, I can't seem to find any documentation on how I should go about creating fields that can be generated through JavaScript. I have created a custom field to serve as the URL slug of a post, currently its used by manually typing out the title of the post in a URL safe format in the custom field. Though ideally it would use JavaScript to analyse the title and convert it to a URL safe string, auto-populating the slug and displaying it in the admin UI in a disabled text field.

So basically my question is how to set the value of a field in JavaScript based on the value of another field?

  • Selected Answer
    discord user avatar
    jacobsfletch
    2 years ago

    Hey @peniswafflexd

    Glad to hear of your successes so far. Fortunately, what you describe is a common feature and pretty simple to setup. Since you already have a custom field, you're half way there.

    To read the current value of another field in your document, use the getDataByPath method from the useWatchForm hook. Just send it the name of the field your are looking for. In your case, this is probably title. Now you can format the href using this value, and render an anchor tag on the page.

    To go the extra mile, you can also import Payload's CopyToClipboard component and enhance the user experience.

    import React from 'react';
    import { useWatchForm } from 'payload/components/forms';
    import CopyToClipboard from 'payload/dist/admin/components/elements/CopyToClipboard';
    import { UIField } from 'payload/dist/fields/config/types';
    
    export const AppUrlField: React.FC<UIField> = () => {
      const { getDataByPath } = useWatchForm();
      const title = getDataByPath('title');
      const kebabTitle = title; // convert your title to a kebab-case string here, there are many ways to do this
      const href = `https://yourapp.com/${kebabTitle}`; // swap in your own top-level domain here
    
      return (
        <div>
          <div>
            <span>
              APP URL
            </span>
            <CopyToClipboard value={href} />
          </div>
          <div>
            <a
              href={href}
              target="_blank"
              rel="noopener noreferrer"
            >
              {href}
            </a>
          </div>
        </div>
      );
    };
    4 replies
  • default discord avatar
    peniswafflexd2 years ago

    Hey @jacobsfletch ahh this is very helpful but not particularly what I was looking for, this will display exactly what I want in the admin UI, however, this won't actually change the value of the field in the database will it?

    I need the 'kebab-title' to accessible via the API, and this seems to only change it on the front end and not store it? Am I correct or am I misinterpreting how this works?

    Thanks for the quick reply!

  • discord user avatar
    jacobsfletch
    2 years ago

    Yep that makes perfect sense.

    For that you'll want to render a custom text field (as opposed to a ui field illustrated above). To do this, you can leverage the setValue method from the useField hook to update the value of the field every time the title changes. We'll still use the useWatchForm hook to keep up-to-date with the current document.

    Then to go the extra mile again, we can also render Payload's text input with current value, so that the UI stays consistent with other fields in the admin panel.

    import React, { useEffect } from 'react';
    import { Props as TextFieldType } from 'payload/dist/admin/components/forms/field-types/Text/types';
    import TextInputField from 'payload/dist/admin/components/forms/field-types/Text/Input';
    import { useField, useWatchForm } from 'payload/components/forms';
    import { FieldType as FieldType, Options } from 'payload/dist/admin/components/forms/useField/types';
    
    export const AppURL: React.FC<TextFieldType & {
      path: string
    }> = (props) => {
      const {
        label,
        name,
        path,
      } = props;
    
      const field: FieldType<string> = useField({
        label,
        name,
        path
      } as Options);
    
      const { fields } = useWatchForm();
    
      const {
        value,
        setValue,
        showError
      } = field;
    
      useEffect(() => {
        const { title: { value: title } } = fields;
        const kebabTitle = title; // convert your title to a kebab-case string here, there are many ways to do this
        const newHref = `https://yourapp.com/${kebabTitle}`;
        setValue(newHref);
      }, [
        fields,
        setValue,
      ]);
    
      return (
        <TextInputField
          path={name}
          name={name}
          onChange={setValue}
          value={value}
          showError={showError}
          style={{
            marginBottom: 0
          }}
        />
      );
    };
  • default discord avatar
    peniswafflexd2 years ago

    Thats it! Thanks so much!
    I didn't notice any react hooks in the documentation on the site, is this documentation available somewhere?

    Also I don't know how to mark your comment as the answer

  • discord user avatar
    jacobsfletch
    2 years ago

    No problem! Documentation is in progress.

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.