UUIComponents - Owner is nullptr in IsDataValid

Hi Support,

I have found that the IsDataValid is run on UIComponents before the component is initialized causing a nullptr, this makes validation on things such as checking the component is attached to a specific type e.g. a button, currently impossible.

I have raised a hacky fix in this PR - bugfix: UIComponent will now not have a nullptr as owner in IsDataValid by r-jonathan-wright · Pull Request #14730 · EpicGames/UnrealEngine and am hoping that the engineering team at epic can help clean this up/provide a better solution

Update: i have just discovered this fix won’t work for headless unreal instances, the UUIComponent is created via the RegenerateBlueprintClass flow, which ends up with a nullptr as owner as Initialize is never called on the UUIComponent.

I will likely need to wait for a proper solution

Thanks

Steps to Reproduce

  • Create a UUIComponent
  • Add a isDataValid override
  • Access the owner field (see it is null)

Hi,

I’m not sure we need to initialize the component (which feels a bit riskier), instead we could probably pass a reference to the owning widget through UUIComponentWidgetBlueprintExtension::ValidateComponents by resolving it against the widget tree at that point. I think the best approach here would be a separate virtual function to override (i.e. IsDataValidForOwner) that falls back to IsDataValid but includes the extra parameter for the owning widget. Before I go too far down that route, I’m curious if that would meet your needs for whatever sorts of validators you’re looking to write. I’m thinking something like this:

const UWidgetBlueprint* WidgetBlueprint = GetWidgetBlueprint();
const UWidgetTree* WidgetTree = WidgetBlueprint ? WidgetBlueprint->WidgetTree : nullptr;
 
ComponentContainer->ForEachComponentTarget([&](const FUIComponentTarget& ComponentTarget)
{
	UUIComponent* Component = ComponentTarget.GetComponent();
	if (!Component)
	{
		return;
	}
 
	UWidget* OwnerWidget = (WidgetTree ? const_cast<FUIComponentTarget&>(ComponentTarget).Resolve(WidgetTree) : nullptr);
 
	Result = CombineDataValidationResults(Result, Component->IsDataValidForOwner(OwnerWidget, Context));
});

Would that approach work for you?

Sorry for the delay, this is checked in now at CL# 53583859. Let me know if that works for you and we’ll close out the PR. Thanks!

Hi Cody, yes that would work for us, could you provide a CL for us to test this approach?

Thankyou :slight_smile:

Thanks, this works for us.

I think future developers may still expect GetOwner to return something in IsDataValid but understand this is a bit harder to get to work.