umbraco / Umbraco-CMS

Umbraco is a free and open source .NET content management system helping you deliver delightful digital experiences.
https://umbraco.com
MIT License
4.41k stars 2.66k forks source link

Setting default value in SendingContentModel event has no effect #14215

Open max-maurice opened 1 year ago

max-maurice commented 1 year ago

Which Umbraco version are you using? (Please write the exact version, example: 10.1.0)

8.18.7

Bug summary

Using the code from the Umbraco documentation at https://our.umbraco.com/documentation/reference/events/EditorModel-Events/ with only the content type alias and property type alias changed. When creating a new block in the editor, the settings should receive a default value for the custom visible property. This worked in Umbraco 8.17.1, but doesn't after the update to 8.18.7. The code gets called and changes the Value property as expected. The UI however shows the TrueFalse editor in the false state instead of true. I've also tried using text box property types using string default values without success.

Specifics

No response

Steps to reproduce

Expected result / actual result

No response


_This item has been added to our backlog AB#29675_

github-actions[bot] commented 1 year ago

Hi there @max-maurice!

Firstly, a big thank you for raising this issue. Every piece of feedback we receive helps us to make Umbraco better.

We really appreciate your patience while we wait for our team to have a look at this but we wanted to let you know that we see this and share with you the plan for what comes next.

We wish we could work with everyone directly and assess your issue immediately but we're in the fortunate position of having lots of contributions to work with and only a few humans who are able to do it. We are making progress though and in the meantime, we will keep you in the loop and let you know when we have any questions.

Thanks, from your friendly Umbraco GitHub bot :robot: :slightly_smiling_face:

andr317c commented 1 year ago

Hey, I tried reproducing this. Just to be sure, does your SubscribeToEditorModelEventsComposer.cs also look like this?

using System;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Web.Editors;
using Umbraco.Web.Models.ContentEditing;

namespace My.Website
{
    [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
    public class SubscribeToEditorModelEventsComposer : ComponentComposer<SubscribeToEditorModelEvents>
    {
       // This automatically adds the component to the Components collection of the Umbraco composition
    }

    public class SubscribeToEditorModelEvents : IComponent
    {
        // Initialize: runs once when Umbraco starts
        public void Initialize()
        {
            EditorModelEventManager.SendingContentModel += EditorModelEventManager_SendingContentModel;
        }

        // Terminate: runs once when Umbraco stops
        public void Terminate()
        {
            // Unsubscribe during shutdown
            EditorModelEventManager.SendingContentModel -= EditorModelEventManager_SendingContentModel;
        }

        private void EditorModelEventManager_SendingContentModel(System.Web.Http.Filters.HttpActionExecutedContext sender, EditorModelEventArgs<Umbraco.Web.Models.ContentEditing.ContentItemDisplay> e)
        {
            // Set a default value for a NewsArticle's PublishDate property, the editor can override this, but we will suggest it should be today's date
            if (e.Model.ContentTypeAlias == "mBlock")
            {
                //access the property you want to pre-populate
                //in V8 each content item can have 'variations' - each variation is represented by the `ContentVariantDisplay` class.
                //if your site uses variants, then you need to decide whether to set the default value for all variants or a specific variant
                // eg. set by variant name:
                // var variant = e.Model.Variants.FirstOrDefault(f => f.Name == "specificVariantName");
                // OR loop through all the variants:
                foreach (var variant in e.Model.Variants){
                    //check if variant is a 'new variant' - we only want to set the default value when the content item is first created
                    if (variant.State == ContentSavedState.NotCreated){
                        // each variant has an IEnumerable of 'Tabs' (property groupings) and each of these contain an IEnumerable of `ContentPropertyDisplay` properties
                        var pubDateProperty = variant.Tabs.SelectMany(f => f.Properties).FirstOrDefault(f => f.Alias.InvariantEquals("visible"));
                        if (pubDateProperty!=null){
                            // set default value of the publish date property if it exists
                            pubDateProperty.Value = true;
                        }
                    }
                }
            }
        }
    }
}
max-maurice commented 1 year ago

Hi @andr317c

thanks for trying to reproduce. Yes, the code looks exactly like yours. I've just checked using your code, but the visible property on new block list items is always false.

The XHR to GetEmptyByKey returns true for the visible property, though:

{
    "3": {
        "label": "Sichtbar",
        "description": null,
        "view": "boolean",
        "config": {
            "default": false,
            "showLabels": false,
            "labelOn": null,
            "labelOff": null
        },
        "hideLabel": false,
        "labelOnTop": false,
        "validation": {
            "mandatory": false,
            "mandatoryMessage": null,
            "pattern": null,
            "patternMessage": null
        },
        "readonly": false,
        "id": 0,
        "dataTypeKey": "92897bc6-a5f3-4ffe-ae27-f2e7e33dda49",
        "value": true,
        "alias": "visible",
        "editor": "Umbraco.TrueFalse",
        "isSensitive": false,
        "culture": null,
        "segment": null
    }
}

Looks like the IComponent is not the issue, but a "property editor" on the client side?

andr317c commented 1 year ago

Hey again!

I tried setting it up on version 8.17.1 as you mentioned above, and it works. So that must mean that this is a regression issue somewhere between 8.17.1 -> 8.18.7. I will mark this issue as up for grabs since we have good reproduction steps.

github-actions[bot] commented 1 year ago

Hi @max-maurice,

We're writing to let you know that we would love some help with this issue. We feel that this issue is ideal to flag for a community member to work on it. Once flagged here, folk looking for issues to work on will know to look at yours. Of course, please feel free work on this yourself ;-). If there are any changes to this status, we'll be sure to let you know.

For more information about issues and states, have a look at this blog post.

Thanks muchly, from your friendly Umbraco GitHub bot :-)

max-maurice commented 5 months ago

Reverting the changes made in commit 477697a70cd8b10703f6cf428ceb1da47bfad257 would resolve this issue. Any ideas how we could solve this without affecting #11423?

max-maurice commented 5 months ago

Yes, I might have: As this issue is about default values for new block items, we could check for the property being in the dataModel using in, instead of testing its value:

Edit 03.06.2024: following code is located in src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js

BEFORE

for (var p = 0; p < tab.properties.length; p++) {
  var prop = tab.properties[p];

  if (dataModel[prop.alias]) {
    prop.value = dataModel[prop.alias];
  }
}

AFTER

for (var p = 0; p < tab.properties.length; p++) {
  var prop = tab.properties[p];

  if (prop.alias in dataModel) {
    prop.value = dataModel[prop.alias];
  }
}

This way, setting prop.value does not depend on the value of dataModel[prop.alias] like before, but on the existence of the property in dataModel.

11423 should still be solved, because we're not checking the value at all.