Skip to content

Unable to set node name on Content Workspace Content - without using a setTimeout #20544

@warrenbuckley

Description

@warrenbuckley

Which Umbraco version are you using?

16.3.0

Bug summary

I have a custom workspace context trying to set a node name for certain new nodes created.
I am having to use a hacky approach of wrapping a method call in a timeout set to 0ms in order for the code to work and set the node name.

My assumption would be if that I have awaited the isLoaded() method/promise on the Content Workspace that everything has been initialized that it needs and I could use and set what I need to do.

Specifics

No response

Steps to reproduce

Workspace context

import { UmbControllerBase } from "@umbraco-cms/backoffice/class-api";
import { UmbContentWorkspaceContext } from "@umbraco-cms/backoffice/content";
import { UmbControllerHost } from "@umbraco-cms/backoffice/controller-api";
import { UMB_CONTENT_WORKSPACE_CONTEXT } from "@umbraco-cms/backoffice/content";
import { UmbVariantId } from "@umbraco-cms/backoffice/variant";
import { UMB_APP_LANGUAGE_CONTEXT } from "@umbraco-cms/backoffice/language";
import type { UmbLanguageDetailModel } from '@umbraco-cms/backoffice/language';

export class SetDashForNodeName extends UmbControllerBase {
  #workspaceContext?: UmbContentWorkspaceContext;
  #languages?: Array<UmbLanguageDetailModel>;
  #isNew: boolean = false;

/**
 * We use this to set the node name to a dash for all languages when creating a new content item
 * The conditions for this workspace context is set in the manifest to only apply to specific content types
 * Such as Tweet etc...
 * 
 * WHY: We use a dash as a node name placeholder and when the node is saved a C# Saving event/notification
 * Then runs logic to determine the default node name based on properties and other values from the node
 */

  constructor(host: UmbControllerHost) {
    super(host);

    this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (appLanguageContext) => {
      this.observe(appLanguageContext?.languages, (languages) => {
        this.#languages = languages;
      });
    });
    

    this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, async (contentWorkspaceCtx) => {
      this.#workspaceContext = contentWorkspaceCtx;

      if(!this.#workspaceContext){
        return;
      }

      // Wait for the workspace to be fully loaded before observing
      await this.#workspaceContext.isLoaded();
      
      this.observe(this.#workspaceContext.isNew, (isNew) => {
        this.#isNew = isNew ?? false;

        // Throws an error if we try this without a timeout wrapped around it
        //this.#updateNodeName();

        // YUK - why we do need a timeout to wrap the updateNodeName method ?
        // Without it the setName on the workspace complains with this error
        // I would have thought that by awaiting the isLoaded above 
        // That everything would have been initialized and ready to use

        /*
        reportUnhandledError.js:10 
          Uncaught Error: Data is missing
              at #e (content-data-manager.ts:90:27)
              at Mt.updateVariantData (content-data-manager.ts:65:9)
              at Ut.setName (content-detail-workspace-base.ts:502:14)
              at #o (set-dash-for-node-name.ts:77:31)
              at Object.next (set-dash-for-node-name.ts:46:14)
        */

        setTimeout(() => {
          this.#updateNodeName();
        }, 0); // 0ms delay
        
      });
    });
  }

 

  #updateNodeName(){
      // Check we have workspace context & all languages from observable set
      if (!this.#workspaceContext || !this.#languages){
        return;
      }

      if(!this.#isNew){
        console.log('[Set Dash For Node Name] - Node is NOT a new node, skipping setting node name to dash');
        return;
      }

      const defaultLang = this.#languages.find(lang => lang.isDefault);

      if(!defaultLang){
        console.warn('[Set Dash For Node Name] - No default language found, cannot set node name to dash');
        return;
      }

      // We only need to set the dash for the default language
      this.#workspaceContext?.setName('-', new UmbVariantId(defaultLang.unique));
    }
}

export default SetDashForNodeName;

Manifest

import { UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS } from "@umbraco-cms/backoffice/content-type";

export const manifests: Array<UmbExtensionManifest> = [
    {
        type: "workspaceContext",
        name: "[Consilium] - Set dash for node name",
        alias: "Consilium.WorkspaceContext.SetDashForNodeName",
        api: () => import('./set-dash-for-node-name'),
        conditions: [
            {
                alias: UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS,
                oneOf: [
                    "pressMaterialPage", 
                    "meetingPage", 
                    "informalMeetingPage", 
                    "tweet", 
                    "presidentNewsPage"
                ]
            }
        ]
    }
];

Expected result / actual result

That I am able to set the nodeName for new content nodes without having to do a hacky workaround of using a timeout.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions