What I can improve in my workflow? My Component-Based workflow described

Hello, in my main job, I am a fullstack web developer and at this time I mostly writing components in Vue.js

I wanted to get closer to component-based development just like in Vue.js.

Here it my workflow with components and from you I want to know, what I can do better.

The one thing I know is wrong, is using “Container” components as instantiating wrapper around wanted custom component.

Here is my example setup
7634914--950605--image (1).png

Here I post content of every single file with some description

CustomComponent.cs is my simple custom VisualElement, which just have to show some label in red rectangle
CustomComponent.cs

using UnityEngine.UIElements;

public class CustomComponent : VisualElement
{
    public new class UxmlFactory : UxmlFactory<CustomComponent> { }

    private Label _label;
   
    public CustomComponent()
    {
        VisualTreeAsset asset = UxmlManager.Instance.uxmlDatabase.customComponent;
        asset.CloneTree(this);

        _label = this.Q<Label>();
    }

    public void SetText(string text)
    {
        _label.text = text;
    }
}

CustomComponent.uxml
CustomComponent.uxml

<ui:UXML class="custom-component-root" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <Style src="CustomComponent.uss"/>
    <ui:VisualElement class="custom-component">
        <ui:Label/>
    </ui:VisualElement>
</ui:UXML>

Its wrapping container used only for instantiating and then accessing its only one and its methods/properties

CustomComponentContainer.cs

using UnityEngine.UIElements;

public class CustomComponentContainer : VisualElement
{
    public new class UxmlFactory : UxmlFactory<CustomComponentContainer> { }

    public CustomComponentContainer()
    {
        VisualTreeAsset asset = UxmlManager.Instance.uxmlDatabase.customComponentContainer;
        asset.CloneTree(this);
    }
}

CustomComponentContainer.uxml
CustomComponentContainer.uxml

<ui:UXML class="custom-component-container-root" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <Style src="CustomComponentContainer.uss" />
    <CustomComponent />
</ui:UXML>

And the FooBar.cs, which is just for imagination how to use my . I wrote some comments, so I hope you will understand to it

FooBar.cs

using UnityEngine.UIElements;

namespace _Project.Components.ForumTemp
{
    public class FooBar : VisualElement
    {

        private VisualTreeAsset _customComponentContainer;

        public FooBar()
        {
            _customComponentContainer = UxmlManager.Instance.uxmlDatabase.customComponentContainer;
        }
       
       
        private void OnDataFetchedFromServer()
        {
            string[] dataFromServer = {"data1", "data2", "data3"};
           
            foreach (string item in dataFromServer) {
               
                //Here I instantiate the container component, which contains my CustomComponent which I want to call methods on
                TemplateContainer templateContainer = _customComponentContainer.Instantiate();
               
                //Here I add it to the elements hierarchy
                this.Add(templateContainer);
               
                //Here I obtain it
                CustomComponent customComponent = templateContainer.Q<CustomComponent>();
               
                //And I can call methods on it
                customComponent.SetText(item);
               
                //The results are 3 Visual Elements which I can modify. In this example I have set them "data1", "data2", and "data3" labels
            }
           
        }

    }
}

And now I want to know from you:

  • It is possible to work with UIElements like this way?
  • Is there a way how to get rid off these *Container.cs components and instantiate and access my components without need of these Containers?
  • What you suggest to improve? :slight_smile:

Thank you all for every comment and suggestion!

If you already have a direct code dependency on CustomComponent, you don’t need to go through this indirection. unless your container adds specific style through its CustomComponentContainer.uss.

Why not do something like:

  private void OnDataFetchedFromServer()
        {
            string[] dataFromServer = {"data1", "data2", "data3"};
          
            foreach (string item in dataFromServer) {
              
                //Here I add it to the elements hierarchy
                var customComponent = new CustomComponent();
                this.Add(customComponent );
              
                //Here I obtain it
             
                //And I can call methods on it
                customComponent.SetText(item);
              
                //The results are 3 Visual Elements which I can modify. In this example I have set them "data1", "data2", and "data3" labels
            }
          
        }

That being said, I’m not familliar with Vue.js… you might have some valid separation of concern designs reasons to go this way.

@uMathieu oh my god, Im soooooooo DUMB! Thank you, you totally solved mu struggles. Use of containers are not speciallity of Vue.js, it was just mine workaround, I didnt realised that I can do “new CustomComponent” lol, really, thank you!

@uMathieu maybe Unity could improve UIElements documentation with more examples, as far as I know there are just tutorials with extending of EditorWindow, or use in Editor mode, but no examples like mine use-case