Really struggling with getting the Admin UI to update after updating the data in a custom field.

default discord avatar
rhysmakesthingslast year
1 2

I have two cases I'm looking at. One is adding a row to an array field from a separate custom text field. The custom text field does a query to a backend server and then I try to add the results of that query as an item in my array field

dispatchField({type:'ADD_ROW',path:"otherField",rowIndex:((otherFields.value as number)), subFieldState:state})
Already I'm not sure if i'm specifying the rowIndex properly but it seems to be required, I'm grabbing the arrays value which appears to actually be its length from useFormFields. This actually does work properly in terms of the data getting updated, but the admin ui does not update at all even though I have used dispatchField so I would expect the new item to become visible in the array. If I manually add a row or save the form then the row does become visible. I've tried "setModified" from useForm and that doesn't work. "submit" from useForm does work but I don't want to have to save the form in order for the UI to update.

The second case is I wanted to add a custom cell for collection List views that provided a button that would perform an update. In this case i'm trying to add a "publish" and a "delete" button cell so that these things can be conveniently done from the list page. This time I used the api to update the collection and that worked successfully but I could not find a sensible way to refresh the UI to display the new changes caused by my custom component.

Please can someone direct me to a way to trigger an update of the admin ui in a sensible way.

  • Selected Answer
    default discord avatar
    rhysmakesthingslast year

    Seems like the following extra lines were required before replaceState
    newState.myArray.initialValue = rowIndex+1
    newState.myArray.valid = true
    newState.myArray.disableFormData = true

    Especially disableFormData seems to be important. Not totally clear what this field does but seems to be working now.

  • discord user avatar
    jmikrut
    last year

    Hey @rhysmakesthings — I can hopefully give you some answers here.

    So, we're about to "flatten" the way that array / block row state is managed to make this all significantly simpler, but for now, the reason your array is not updating in UI is because it maintains its own internal row state in addition to the form state.

    If you trigger a full refresh of the form after updating a row however, the array field will recalculate its own internal row state and rerender accordingly. This is our suggested approach for now, and I gave an example on how to do this below:

    #2427 (comment)

    Take a shot at this. As I said, we are working on some ways to make updating array-based fields significantly easier, but right now, this is the move. 👍

  • default discord avatar
    rhysmakesthingslast year

    Thanks for the quick reply! Good to hear there are more updates on the way.

    That seems to work well but only if the array already has a value in it. If I'm starting from an empty array and I add something it doesn't appear to update. I also sometimes get "CastError: Cast to embedded failed for value "1" (type number) at path "myArray" because of ObjectParameterError at model.Query.exec (/node_modules/mongoose/lib/query.js:4789:21)" after I add the first row (don't see an update) and save so maybe I'm missing a step?

    const {fields,replaceState} = useForm()
    function addFieldState(key,v,state,rowIndex,path){
        state[`${path}.${rowIndex}.${key}`] = {passesCondition: true, valid: true, value: v, initialValue:v}
    }
    fetch("i grab something from my own api here").then( resp => { return resp.json() }).then(data => {
        <validate data>
        const newState = {...fields}
        var rowIndex = ((myArray.value as number)) //hopefully adds to the end of the list, this could be part of where I'm going wrong
        createSubFieldState("id",data.id,newState,rowIndex,"myArray")
        createSubFieldState("title",data.title,newState,rowIndex,"videos")
        newState.myArray.value = rowIndex+1 //seems to be required but could also be part of the problem
        // not sure if this is required
        //newState.myArray.initialValue = rowIndex
        replaceState(newState)
    

    I've tried a few different variations on this. id and title are both type string in the field config.

    Any thoughts on the second case I mention in my original post? The sort button on those pages cause a rerender of the table but they also update the url and it seems only changing the sorting method in the url will trigger the rerender. I'm trying to include a "publish" button in a Cell that grabs the current time and updates the relevant item which I can do in the data using the api but I then want it to update in the admin UI as well.

    I've just seen that you also provide a way to use a completely custom views.List component which might be the way to go if I want to achieve the publish button and updating the list instead of just using a custom Cell component. Or to display the data in my own custom cell component but that probably wouldn't update the sorting.

    2 replies
    default discord avatar
    rhysmakesthingslast year

    Seems like the following extra lines were required before replaceState
    newState.myArray.initialValue = rowIndex+1
    newState.myArray.valid = true
    newState.myArray.disableFormData = true

    Especially disableFormData seems to be important. Not totally clear what this field does but seems to be working now.

    default discord avatar
    rhysmakesthingslast year

    Regarding the second case I found a workaround, it's a bit complicated perhaps but it works.

    First set up a CustomProvider using the payload.config.ts > admin > components > providers config to specify a custom provider based on the custom provider in the git repo test folder as a basis.

    Then, in the custom Cell component that sends the api request, import the custom providers hook and use it and set the state to the data.doc returned by the api call.

    Then, in a custom List component (defined in the collection config > admin > components > views > List) import the default List from 'payload/dist/admin/components/views/collections/List/Default', return <List {...props}> from your custom component which will cause the List view to display as normal, and import the custom provider hook again this time updating props.data.docs by finding the doc with the same id as your custom provider hook state and replacing it with the custom provider hook state.

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.