Specify a default value for a content node name (multiple variants)

Hi,

Looking into some advice/pointers on how to specify a default value for a content node (in multiple variants/languages). Anyone has any idea on how to tackle this?

–Dirk

A few different approaches depending on your needs:

1. Data Type Default Value

If the property is based on a standard data type (textbox, number, checkbox, etc.), you can set a default value on the data type itself.

  • Go to Settings → Data Types

  • Edit the data type used by your property

  • Most editors (e.g. textbox, number, checkbox, dropdown) have a “Default value” field.

  • This will apply when a property is empty across all variants.
    :warning: Limitation: this applies to all cultures, not culture-specific defaults.


2. Content Templates (a.k.a. Blueprints)

Umbraco has “content templates” (formerly blueprints).

  • Create a content node with all default values filled in for each language variant.

  • Save it as a content template.

  • When editors create new content of that type, they can pick this template and it will prefill the values.
    Good for multi-language because you can set defaults per language variant.


3. Code-based Defaulting via Event Handlers

If you need something more dynamic (e.g. per culture, per user, or conditional), you can hook into Umbraco’s content events. For example:

using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;

public class SetDefaultValuesHandler : INotificationHandler<SavingNotification>
{
    public void Handle(SavingNotification notification)
    {
        foreach (var content in notification.SavedEntities)
        {
            // Example: set default only on new nodes
            if (content.HasIdentity) continue;

            // Variant-aware property setting
            foreach (var culture in content.AvailableCultures)
            {
                var value = content.GetValue("myPropertyAlias", culture);
                if (string.IsNullOrWhiteSpace(value?.ToString()))
                {
                    content.SetValue("myPropertyAlias", "Default text here", culture);
                }
            }
        }
    }
}

  • Runs whenever content is saved.

  • Ensures new nodes have a default in every culture variant.

  • You can even make the default value different per culture (e.g. English → “Hello”, French → “Bonjour”).


4. Dictionary Items for Multi-language Defaults

If you want true multi-language defaults, use dictionary items:

  • Create dictionary entries for the default values.

  • In your event handler, set the property value from the dictionary item depending on the culture.

  • That way you don’t hard-code the text in code.

Example:

var defaultValue = _localizationService.GetDictionaryValue("Defaults.MyProperty", culture);
content.SetValue("myPropertyAlias", defaultValue, culture);

Hi @deepakaggrawal ,

Thanks for your reply, but not sure your suggestions will work in case i need to set the default node name, not any property of any sort, but the actual node name.
So solution 1 and 4 are not to be considered valid options
Option 3 won’t work either cause we need to set the node name first before we can do a save
Option 2 can be considered, which I indeed have done, but requires some extra clicks from ui point of view (I’ve no issues doing so, but it has created frustration with editors before, yet the reason why we’re looking into alternatives)

Maybe would need to explain a bit better the (edge) use case… we have 24 languages, and the node name will be derived from some specific properties on the content item (Let’s say a title and date). Once the node gets saved, we do use indeed the save event notification handler to change the node name based on a specific formatting of the title and date. However, before we get there (the save action), the node name MUST be set, and that’s the current reason why we’re trying to set the node name (which is the same in all 24 languages) to be able to perform the save.

I know it’s also possible to have properties “listen” to changes in other properties and act upon (eg: change values), but in this case, I would need to be able to change the node name and not any specific property…

–Dirk

I’ll follow up with solution i came up with and is working fine:

export class SetNodeNameBasedOnDate extends UmbControllerBase {
  #workspaceContext?: UmbContentWorkspaceContext;
  #currentDate?: string;
  #languages?: Array<UmbLanguageDetailModel>;

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

    this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => {
      this.#workspaceContext = context;
      this.#setupPropertyWatcher();
    });

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

  async #setupPropertyWatcher() {
    if (!this.#workspaceContext) return;

    // Await the property observable
    const dateObservable = await this.#workspaceContext.propertyValueByAlias("date");

    if (dateObservable) {
      this.observe(dateObservable, (value) => {
        setTimeout(() => {
          this.#currentDate = value?.toString();

          this.#updateNodeName(this.#currentDate, this.#languages);
        }, 0); // 0ms delay lets the event loop finish updating the model
      });
    }
  }

  async #updateNodeName(value: string | undefined, languages: UmbLanguageDetailModel[] | undefined) {
    // Returned value from property is either yyyy-MM-dd HH:mm or yyyy-MM-dd HH:mm:ss - Depends on whether seconds fragment of the date was set
    var date = value!.length === 16 ? value + ":00" : (value as string);

    languages!.forEach(language => {
      this.#workspaceContext!.setName(date, UmbVariantId.FromString(language.unique));
    });
  }
}

export default SetNodeNameBasedOnDate ;
1 Like

Thanks. But how do you register this in a manifest? Which extension type would it be?

Fair point, it’s registered as a workspace action


{
type: "workspaceContext",
name: "[Consilium] - Set 'Tweet' node name based on date property",
alias: "Consilium.WorkspaceContext.SetTweetNodeName",
api: () => import('./set-tweet-node-name'),
conditions: [
{
alias: UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS,
match: "tweet"
}
]
},

1 Like

Thanks, that is an incredibly useful technique, works perfectly. And very cool that it updates live, didn’t know you could do that now.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.