Cannot update block

Hello all!

Iā€™m having issues updating a block record via Datoā€™s Data Management API. Iā€™m using the official javascript client (cma-client-node).

The following structure has been setup:

Model: Article > Article Content Body (Modular Content consisting of ā€œRichtextā€ blocks) > Content (Block: Structured Text) > Richtext Review (Block)

Is there any extra documentation available besides https://www.datocms.com/docs/content-management-api/resources/item/update? Because I cannot get it to work. The documentation states things like ā€œitemIdā€ but what does it mean? Record Id? Block Id?

Hi @bhordijk,

Welcome to the Dato forum!

Did you happen to scroll down far enough to see the full examples, e.g. https://www.datocms.com/docs/content-management-api/resources/item/update#update-a-block-record-in-a-modular-content-field? If that still isnā€™t enough, could you please let me know what model this is for (its URL or ID) and what you want to add to it? I can write you a sample script and test it on a sandbox environment for you, if that would help.

You can PM me or email support@datocms.com if you donā€™t want to share that publicly. Thank you!

Iā€™m in the process of making a clearer example for the docs page too. Please give me a moment and Iā€™ll post it here once itā€™s ready.

Hereā€™s an updated example thatā€™s hopefully clearerā€¦? Let me know if I can explain anything.

Itā€™ll be in the official docs once CI/CD passes, but in the meantime, here it is:

The updated example

import {buildClient} from '@datocms/cma-client-node';

async function run() {
    // Make sure the API token has access to the CMA, and is stored securely
    const client = buildClient({apiToken: process.env.DATOCMS_API_TOKEN});

    // These define what to update
    const recordId = "A4gkL_8pTZmcyJ-IlIEd2w"; // The record's unique ID
    const fieldWithBlocks = 'modular_content_field' // Which record field are the blocks in?
    const blockId = 'ToBApjdYQaCgeFJxp_ty0A'; // ID of the block we want to update ("Example block #1")
    const blockFieldsToUpdate = { // Inside the block, what are we updating?
        title: 'Example block #1 (Updated title)' // Update the title
    }

    // Get the current record
    const currentRecord = await client.items.find(recordId, {
        nested: true // Also fetch the content of nested blocks, not just their IDs
    });

    console.log('currentRecord before update', JSON.stringify(currentRecord[fieldWithBlocks], null, 2))

   // Build the update before sending it
    const currentBlock = currentRecord[fieldWithBlocks].find(block => block.id === blockId) // The block's existing content
    const updatedBlock = {
        ...currentBlock, // Keep its existing metadata
        attributes: {
            ...currentBlock.attributes, // Keep existing attributes that we didn't update
            ...blockFieldsToUpdate // Inject updated fields
        }
    }
    const updatedFieldWithBlocks = currentRecord[fieldWithBlocks].map(block => // Map through existing blocks so we keep their ordering
        block.id === updatedBlock.id
            ? updatedBlock //  If it's the block we want to update, inject the updated data
            : block.id // Otherwise, just provide the old block's ID and the API will know to keep it unchanged
    )

    // Perform the update by actually sending what we built to the API
    const updatedRecord = await client.items.update(recordId, {
        [fieldWithBlocks]: updatedFieldWithBlocks // The record field to update
        // We don't have to specify the other fields. The API will keep them the same.
    })

    console.log('Updated record field. By default we only return the block IDs.', updatedRecord[fieldWithBlocks])

    // (Optional, only if you want to verify it manually) Make another request to fetch the updated nested blocks
    const updatedRecordWithNestedBlocks = await client.items.find(recordId, {
        nested: true // Also fetch the content of nested blocks, not just their IDs
    });

    console.log('Updated record field with nested blocks', updatedRecordWithNestedBlocks[fieldWithBlocks])

}

run();

Before the update

currentRecord before update [
  {
    "type": "item",
    "attributes": {
      "title": "Example block #1",
      "nested_modular_content_field": [
        {
          "type": "item",
          "attributes": {
            "title": "Nested block inside example block #1",
            "nested_modular_content_field": []
          },
          "relationships": {
            "item_type": {
              "data": {
                "id": "cR-9e-65SNat84KEs5M22w",
                "type": "item_type"
              }
            }
          },
          "id": "YByg71hHQzOxIow2P6eujg"
        }
      ]
    },
    "relationships": {
      "item_type": {
        "data": {
          "id": "cR-9e-65SNat84KEs5M22w",
          "type": "item_type"
        }
      }
    },
    "id": "ToBApjdYQaCgeFJxp_ty0A"
  },
  {
    "type": "item",
    "attributes": {
      "title": "Example block #2",
      "nested_modular_content_field": []
    },
    "relationships": {
      "item_type": {
        "data": {
          "id": "cR-9e-65SNat84KEs5M22w",
          "type": "item_type"
        }
      }
    },
    "id": "YGrrPYrkSNaq-dBaP7aSaQ"
  }
]

After the update

If you just log updatedRecord, youā€™ll get back only the block IDs:

Updated record field. By default we only return the block IDs. [ 'ToBApjdYQaCgeFJxp_ty0A', 'YGrrPYrkSNaq-dBaP7aSaQ' ]

You have to make another item.find() request to see the updated blocks with their nested content:

Updated record field with nested blocks [
  {
    type: 'item',
    attributes: {
      title: 'Example block #1 (Updated title)',
      nested_modular_content_field: [Array]
    },
    relationships: { item_type: [Object] },
    id: 'ToBApjdYQaCgeFJxp_ty0A'
  },
  {
    type: 'item',
    attributes: { title: 'Example block #2', nested_modular_content_field: [] },
    relationships: { item_type: [Object] },
    id: 'YGrrPYrkSNaq-dBaP7aSaQ'
  }
]

I hope that helps! Please still feel free to email us with your specific model/record details if youā€™d like me to write a sample script for you.

@roger Thanks for the clarification! Meanwhile I already fixed it by myself but it took a lot of time and trial and error.

Your new documentation is a lot more clearer so I would suggest to update the current documentation as soon as possible :slight_smile:

1 Like

Great, glad it worked, @bhordijk, and sorry I wasnā€™t able to provide the updated example sooner! Itā€™s been committed and will show up on the next deploy (usually a few days).

Iā€™ll be working through and improving our docs over the next few months, so if thereā€™s anything else thatā€™s unclear, please do let us know!