MattHodson
MattHodson

Reputation: 796

Creating a Public String / Public Variable in Blazor?

So I'm trying to get a name from the database, then echo this name using the public string, @namea, wherever I choose on the page.

I have found a way of doing it, however it's so hacky and clearly isn't the way to do it.

So here is my code...

@code{
public string namea = "";
 
 public string cryptoName()
 {
    var test = db.Get("Names");
    namea = db.name;
    return db.name;
 }
}

And the HTML which calls it

<li class="breadcrumb-item active" aria-current="page">
    <small>@namea</small>
</li>

I did think within the @code block, you'd be able to just do the following:

db.Get("Names");
var namea = db.name;

Then reuse namea within the HTML... but adding this into @code, not wrapping within cryptoName() just returns this error.

Please note; I know this is extremely basic, but I'm just looking for best practices. Thanks.

Upvotes: 0

Views: 659

Answers (2)

Grizzlly
Grizzlly

Reputation: 596

The @code block is not something that gets executed when the page loads, it is a "partial class". This is why you can also do code-behind in a separate file. Because it is a class, you obviously cannot call functions directly. That's why you have lifecycle methods.

I believe that @BrianParker's answer is overkill and may be hard to understand if you are new to Blazor. For your specified problem this is something minified:

Index.razor:

@page "/"

<li class="breadcrumb-item active" aria-current="page">
    <small>@name</small>
</li>

Index.razor.cs: (note that if you name your files like this the solution explorer provides a nice hierarchy)

// A bunch of using statements

public partial class Index : ComponentBase //Similar to ControllerBase
{
   [Inject]
   private IApiService ApiService { get; set; }

   string name = "";

   public override async Task OnInitializedAsync() //Comes from ComponentBase
   {
      name = await ApiService.GetNameAsync(); //Simulate a long API or DB call

      await base.OnInitializedAsync();
   }
}

I prefer using the code-behind approach instead of @code because it keeps things organized and IMO complies with SOLID in some way.

Upvotes: 0

Brian Parker
Brian Parker

Reputation: 14593

Class to store the name:

public class SomeConfig
{
    public string Name { get; private set; }

    public event Func<Task> Notify;

    public void SetName(string name)
    {
        Name = name;
        Notify?.Invoke();
    }
}

Inject the class as a service in Program.cs:

builder.Services.AddSingleton<SomeConfig>();

In some component say MainLayout update the name.

@code {
    [Inject]
    private SomeConfig Config { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await Task.Delay(200); // Simulates an Async database call
        Config.SetName("Brian");
    }
}

Then in any component you simply inject the same service and use the name. I created a component just to display the name.

NameView.razor

@implements IDisposable
@Config.Name
@code {
    [Inject]
    private SomeConfig Config { get; set; }

    protected override void OnInitialized() => Config.Notify += OnNotify;

    private Task OnNotify() => InvokeAsync(StateHasChanged);

    public void Dispose() => Config.Notify -= OnNotify;
}

Usage :

 <small><NameView /></small>

Upvotes: 1

Related Questions