Jcl
Jcl

Reputation: 28272

One-way [Parameter] binding programatically

I want to set defaults for parameters on a third-party component. Say I have this:

myBasePage.cs:

public class MyBasePage : ComponentBase
{
  public IEnumerable MyData { get; set; }
}

myPage.razor:

@inherits MyBasePage
<ThirdPartyComponent Data="@MyData" />

Since Data on ThirdPartyComponent is a [Parameter] with a DataHasChanged() virtual method, by rendering the blazor component like that, I'll get one-way binding, and if I change MyData on my page, programmatically, the component will update. This will work fine.

Now, say I can't modify ThirdPartyComponent, but I want to make some defaults in it based on my base page... like so:

myPage.razor:

@inherits MyBasePage
<MyDerivedComponent PageComponent="@this" />

myDerivedComponent.cs:

public class MyDerivedComponent : ThirdPartyComponent 
{
   [Parameter] public MyBasePage PageComponent { get; set; }
   public override void OnInitialized()
   {
      /* Set other parameter defaults */
      this.OtherParameter = 10;

      /* Bind to Data, as if I was passing it as a parameter in the Razor template */
      this.Data = PageComponent.MyData;
   }
}

This line:

this.Data = PageComponent.MyData;

Doesn't create a binding at all (and if I modify MyData, the blazor component doesn't get updated). Is there any way to programmatically create it?

Note: the real ThirdPartyComponent includes not only tons of parameters but also templates, etc. For many reasons, I'd like MyDerivedComponent to be of a derived type, and not a "parent component" with a child of ThirdPartyComponent, if that's possible at all).

Upvotes: 1

Views: 626

Answers (2)

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30036

Is there any way to programmatically create it? Of course, but that doesn't mean that you should.

Parameters should not be set or manipulated within the component code. Parameters are set externally whenever SetParametersAsync is called by the Renderer. If you change them internally you create two versions of the truth.

Upvotes: 1

Henk Holterman
Henk Holterman

Reputation: 273179

This should work:

public class MyDerivedComponent : ThirdPartyComponent 
{
   [Parameter] public MyBasePage PageComponent { get; set; }
   public override void OnInitialized()
   {
      /* Set other parameter defaults */
      this.OtherParameter = 10;


      //this.Data = PageComponent.MyData;
   }
}

 protected override void OnParametersSet()   
 {
    Data = Data ?? PageComponent?.MyData ;  // determine priority
    base.OnParametersSet();
 }

OnParametersSet() notifies the Component that it has new Parameters. The most-derived class can intervene here.

But there is no easy solution for wwhen this.MyData changes, that's out of sight for Blazor.

Upvotes: 1

Related Questions