Bulk editing incorrectly setting all slug fields to the same value

default discord avatar
jakehopking
2 months ago
8

I recently started to use the bulk editing mode within the admin interface.



Unfortunately there's a bug with it. I used to it add a new related items field which I added to my product collection config.



Using the bulk mode correctly allowed me to apply this change to large amount of records successfully. However a few days later after I spent significant time updating individual product records I noticed that every slug was now identical. It appears that every bulk action had applied the same slug to the selection (so each bulk action, say of 30 records, applied the same slug to all).

Add to be clear, I was not editing the slug field.

Due to to the amount of work completed before noticing this error, I was unable to rollback to a db backup. So I've had to go through all 200+ products and fix incorrect slugs.



I suspect the

beforeValidate

hook from the slug field, however I assumed that this use case would have been handled by your bulk editing logic, being that this slug formatting is very common, and indeed appears in your example repos for example??



My slug field looks like this:



import { Field } from 'payload/types';
import { formatSlug, deepMerge } from '../utilities';

export type SlugType = (
  fieldToUse?: string,
  overrides?: Partial<Field>,
) => Field;

export const slug: SlugType = (fieldToUse = 'title', overrides) =>
  deepMerge<Field, Partial<Field>>(
    {
      name: 'slug',
      label: 'Slug',
      type: 'text',
      // Disabled from 1.7.0 due to conflict with no localizations set in global config
      // localized: true,
      admin: {
        position: 'sidebar',
      },
      hooks: {
        beforeValidate: [formatSlug(fieldToUse)],
      },
    },
    overrides,
  );


And the

beforeValidate

formatSlug

fn looks like this:



const format = (val: string): string =>
  val
    .replace(/ /g, '-')
    .replace(/[^\w-/]+/g, '')
    .toLowerCase();

export const formatSlug =
  (fallback: string): FieldHook =>
  ({ value, originalDoc, data }) => {
    if (typeof value === 'string') {
      return format(value);
    }
    const fallbackData =
      (data && data[fallback]) || (originalDoc && originalDoc[fallback]);

    if (fallbackData && typeof fallbackData === 'string') {
      return format(fallbackData);
    }

    return value;
  };


Any thoughts on this? I'd love to use the bulk editing a lot more, but currently I'm locked out due to this error.



Thanks!



Hi @dribbens - any insights on this?

  • discord user avatar
    dribbens
    Payload Team
    2 months ago

    Sorry to hear your slugs got replaced. This is certainly unexpected!


    The update operation that handles many docs does map over the matched on collection records and performs the hook on each one prior to saving. With that I feel our logic is doing what it needs to and that there is something to improve in the

    formatSlug

    function so that this doesn't happen.



    Just to verify though, you said you didn't bulk edit the slug field OR the

    fieldToUse

    that is passed to that hook?



    @jakehopking bulk editing the

    fieldToUse

    would cause this to happen. You can set

    admin.disableBulkEdit

    to

    true

    on the field that determines the slug to make this not possible in the future.

  • default discord avatar
    jakehopking
    2 months ago

    Thanks for getting back to me @dribbens...


    I can confirm that didn't edit the

    fieldToUse

    i.e.

    title

    in this case. I was editing a completely new relationship field.


    So, to confirm if add

    admin.disableBulkEdit

    on the

    title

    , then this shouldn't occur again?

  • discord user avatar
    dribbens
    Payload Team
    2 months ago

    Well that setting would 100% prevent a user from making this error, so you should probably do that. However, you said you didn't do this so there must be something else going on.



    I think I know what the issue is.



    I believe the issue is that the operation code uses an object that is passed around for the data to various hooks, but this ends up being that a reference to the variable is used instead of a newly cloned instance.

  • default discord avatar
    jakehopking
    2 months ago

    Tested and works as you say... thanks 👍

  • discord user avatar
    dribbens
    Payload Team
    2 months ago

    Wait did you make changes to your function to fix this?


    It really should be considered a bug on Payload's side if what I suspect is true.

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    Just curious what version are you on @jakehopking? This sounds like a bug we recently fixed 🤔

  • default discord avatar
    jakehopking
    2 months ago

    @jarrod_not_jared I've upgraded recently to latest, however when this error occurred I was probably a couple of releases behind.



    @dribbens I simply added the

    disableBulkEdit

    to the admin field within the slug function.

  • discord user avatar
    dribbens
    Payload Team
    2 months ago

    It seems to me the version upgrade was more likely the fix as Jarrod pointed out. The disableBulkEdit setting is only going to change the UI and that's not the issue.


    Glad it is working!

Open the post
Continue the discussion in Discord
Like what we're doing?
Star us on GitHub!

Star

Connect with the Payload Community on Discord

Discord

online

Can't find what you're looking for?

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