Search code examples
c#asp.net-coreblazor.net-5asp.net-core-5.0

How to disable the component hierarchy in Blazor?


I would like to achieve a similar effect like in WPF application, where you have a XAML hierarchy and disabling one of the ancestors makes all of its children to be disabled as well.

I could not find any similar approach in Blazor components. I tried to look into Cascading parameters and values but I am not sure if I am on the right track.

Lets say I have a component hierarchy like this below:

<PanelContainer Title="Upload log file">
   <ParagraphRow ParagraphType="ParagraphType.Paragraph1" Label="Some test row">
      <EditBox Text="Some test text" />
   </ParagraphRow>
   <ParagraphRow ParagraphType="ParagraphType.Paragraph2" Label="Some fancy test row disabled" IsEnabled="false">
      <EditBox Text="Some fancy test text" />
   </ParagraphRow>
   <ParagraphRow ParagraphType="ParagraphType.Paragraph3" Label="Some other test row">
      <EditBox Text="Some disabled test text" IsEnabled="false" />
   </ParagraphRow>
</PanelContainer>

All the components here are inherited from a base component class where the IsEnabled Property is declared as a public Property. Each component should behave different according to their IsEnabled value.

For example:
The EditBox should disable the inner input HTML tag, attach the CSS class to the wrapper tag etc. If I just disable the EditBox itself it works like a charm, nothing fancy about it (third ParagraphRow).

I would like to get the same result with the second ParagraphRow, where the row itself has been disabled. Here I would like to make some disabling logic to the row component (CSS class for the label, validation logic changes and so on), but also I would like its children (the EditBox in this case) also be "notified" somehow about being disabled, so it can update by itself to the disabled state.

I would prefer a solution where I don't have to throw bindings and cascading value tags all over the place, so it would "just work" out of the box.

Is it even possible in the Blazor architecture?


Solution

  • You are looking for CascadingValues and Parameters:

    In action:

    Toggling value Check it out at Blazor REPL.

    Simplifiying:

    The base component:

    @code{
        [CascadingParameter]
        public bool IsEnabled { get; set; } = true;
        public string ImEnabled => IsEnabled?"Enabled":"Disabled";
    }
    

    Using components:

    <PanelContainer IsEnabled="isEnabled">
      <ParagraphRow >
        <EditBox />
      </ParagraphRow>
    </PanelContainer>
    <button @onclick="()=>{isEnabled = !isEnabled;}" >Toggle</button>
    @code {
        protected bool isEnabled = true;
    }
    

    PanelContainer

    <h1>PanelContainer</h1>
    <div style="padding-left:10px;">
        <CascadingValue Value="IsEnabled">
        @ChildContent
        </CascadingValue>
    </div>
    @code {
        [Parameter]
        public RenderFragment ChildContent { get; set; }
        [Parameter]
        public bool IsEnabled {get; set; }
    }
    

    ParagraphRow

    @inherits IsEnabledComp
    
    Rapragraph: @ImEnabled
    <div style="padding-left:10px;">
        <CascadingValue Value="IsEnabled">
        @ChildContent
        </CascadingValue>
    </div>
    @code {
        [Parameter]
        public RenderFragment ChildContent { get; set; }
    }
    

    EditBox

    @inherits IsEnabledComp
    EditBox: @ImEnabled
    

    Be free to change what you need to match to your own requirements.