Skip to content

Instantly share code, notes, and snippets.

@georgekosmidis
Last active December 24, 2021 17:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save georgekosmidis/2aabf736158f73c3ed4d2c73d5d1d028 to your computer and use it in GitHub Desktop.
Save georgekosmidis/2aabf736158f73c3ed4d2c73d5d1d028 to your computer and use it in GitHub Desktop.
<p>Current count: @currentCount</p>
<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>
@code {
int currentCount = 0;
void IncrementCount()
{
currentCount++;
}
}
@page "/"
<!-- Add a using to locate the component -->
@using Blazor.WeatherWidget
<!-- Add the component -->
<Component1 />
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
{
"coord": {
"lon": 11.5755,
"lat": 48.1374
},
"weather": [
{
"id": 803,
"main": "Clouds",
"description": "broken clouds",
"icon": "04d"
}
],
"base": "stations",
"main": {
"temp": 291.89,
"feels_like": 291.49,
"temp_min": 289.13,
"temp_max": 293.5,
"pressure": 1020,
"humidity": 64
},
"visibility": 10000,
"wind": {
"speed": 0.89,
"deg": 168,
"gust": 3.13
},
"clouds": {
"all": 77
},
"dt": 1625219902,
"sys": {
"type": 2,
"id": 2002112,
"country": "DE",
"sunrise": 1625195889,
"sunset": 1625253422
},
"timezone": 7200,
"id": 2867714,
"name": "Munich",
"cod": 200
}
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
public class Coord
{
[JsonProperty("lon")]
public double Lon { get; set; }
[JsonProperty("lat")]
public double Lat { get; set; }
}
public class Weather
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("main")]
public string Main { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("icon")]
public string Icon { get; set; }
}
public class Main
{
[JsonProperty("temp")]
public double Temp { get; set; }
[JsonProperty("feels_like")]
public double FeelsLike { get; set; }
[JsonProperty("temp_min")]
public double TempMin { get; set; }
[JsonProperty("temp_max")]
public double TempMax { get; set; }
[JsonProperty("pressure")]
public int Pressure { get; set; }
[JsonProperty("humidity")]
public int Humidity { get; set; }
}
public class Wind
{
[JsonProperty("speed")]
public double Speed { get; set; }
[JsonProperty("deg")]
public int Deg { get; set; }
[JsonProperty("gust")]
public double Gust { get; set; }
}
public class Clouds
{
[JsonProperty("all")]
public int All { get; set; }
}
public class Sys
{
[JsonProperty("type")]
public int Type { get; set; }
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("sunrise")]
public int Sunrise { get; set; }
[JsonProperty("sunset")]
public int Sunset { get; set; }
}
public class Root
{
[JsonProperty("coord")]
public Coord Coord { get; set; }
[JsonProperty("weather")]
public List<Weather> Weather { get; set; }
[JsonProperty("base")]
public string Base { get; set; }
[JsonProperty("main")]
public Main Main { get; set; }
[JsonProperty("visibility")]
public int Visibility { get; set; }
[JsonProperty("wind")]
public Wind Wind { get; set; }
[JsonProperty("clouds")]
public Clouds Clouds { get; set; }
[JsonProperty("dt")]
public int Dt { get; set; }
[JsonProperty("sys")]
public Sys Sys { get; set; }
[JsonProperty("timezone")]
public int Timezone { get; set; }
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("cod")]
public int Cod { get; set; }
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
//...
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
//Adds an IHttpClientFactory and all related services
// and configures the bindings between the WeatherService
// and a named HttpClient
services.AddHttpClient<WeatherService>()
//Sets the time that the HttpMessageHandler can be reused
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
}
//...
}
public class WeatherService
{
private readonly HttpClient _httpClient;
public WeatherService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<Root> Get(string query, string key)
{
var request = new HttpRequestMessage(HttpMethod.Get, $"http://api.openweathermap.org/data/2.5/weather?q={query}&APPID={key}");
request.Headers.Add("User-Agent", "Blazor-Weather-Sample");
request.Headers.Add("X-Code-Source", "https://github.com/georgekosmidis/Blazor.WeatherWidget");
var response = await _httpClient.SendAsync(request);
var result = new Root();
if (response.IsSuccessStatusCode)
{
var responseString = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<Root>(responseString);
}
return result;
}
}
@using Blazor.WeatherWidget.Services;
@using Blazor.WeatherWidget.Models;
@inject IWeatherService service;
<div>@Math.Round(result.Main.Temperature, 1)&nbsp;°C</div>
@code {
private Root result;
protected override async Task OnInitializedAsync()
{
result = await service.Get("Munich, DE", "XXXXXXXXXXXXXXXXXXXXXXX");
}
}
@using Blazor.WeatherWidget.Services;
@using Blazor.WeatherWidget.Models;
@inject IWeatherService service;
@if (result == null)
{
<p><em>Loading...</em></p>
}
else
{
<div>@Math.Round(result.Main.Temperature, 1)&nbsp;°C</div>
}
@code {
private Root result;
protected override async Task OnInitializedAsync()
{
result = await service.Get("Munich, DE", "XXXXXXXXXXXXXXXXXXXXXXX");
}
}
@using Blazor.WeatherWidget.Services;
@using Blazor.WeatherWidget.Models;
@inject IWeatherService service;
@if (result == null)
{
<p><em>Loading...</em></p>
}
else
{
<div>@Math.Round(result.Main.Temperature, 1)&nbsp;°C</div>
<!-- Add an input that is bound to the new property CurrentCity -->
<input value="@CurrentCity" @oninput="@((e) => { CurrentCity = (string)e.Value;})">
<!-- Add a button that onclick runs an event to retrieve data for the typed city -->
<button class="btn btn-info" type="button" @onclick="OnSearchNewCity">Go!</button>
}
@code {
private Root result;
public string CurrentCity { get; set; } = "Munich, DE";
protected override async Task OnInitializedAsync()
{
result = await service.Get(CurrentCity, "XXXXXXXXXXXXXXXXXXXXXXX");
}
protected async Task OnSearchNewCity()
{
//I know, its the same as OnInitializedAsync, but let's move on for now
result = await service.Get(CurrentCity, "XXXXXXXXXXXXXXXXXXXXXXX");
}
}
@using Blazor.WeatherWidget.Services;
@using Blazor.WeatherWidget.Models;
@inject IWeatherService service;
<!-- That's our default tempate -->
@{
RenderFragment defaultTemplate =
@<div>
@if (result != null)
{
<div>@Math.Round(result.Main.Temperature, 1)&nbsp;°C</div>
<!-- Add an input that is bound to the new property CurrentCity -->
<input value="@CurrentCity" @oninput="@((e) => { CurrentCity = (string)e.Value; })">
<!-- Add a button that onclick runs an event to retrieve data for the typed city -->
<button class="btn btn-info" type="button" @onclick="OnSearchNewCity">Go!</button>
}
</div>; <!-- Mind the semicolon here, it marks the end of our template! -->
}
@if (result == null)
{
//We can define a new template for loading too!
<p><em>Loading...</em></p>
}
else
{
//If dev didnt define one, lets use ours
if (CustomTemplate == null)
{
@defaultTemplate
}
else
{
@CustomTemplate(result);
}
}
@code {
private Root result;
//A public parameter, exactly as we did with the CurrentCity parameter
[Parameter]
public RenderFragment<Root> CustomTemplate { get; set; }
[Parameter]
public string CurrentCity { get; set; } = "Munich, DE";
protected override async Task OnInitializedAsync()
{
result = await service.Get(CurrentCity, "XXXXXXXXXXXXXXXXXXXXXXX");
}
protected async Task OnSearchNewCity()
{
//I know, its the same as OnInitializedAsync, but let's move on for now
result = await service.Get(CurrentCity, "XXXXXXXXXXXXXXXXXXXXXXX");
}
}
@page "/"
@using Blazor.WeatherWidget
<!-- Showing weather with the default template -->
<WeatherWidget CurrentCity="London, UK" />
<!-- Using a custom template -->
<WeatherWidget CurrentCity="Munich, DE">
<CustomTemplate>
That's my weather in Munich: <strong>@Math.Round(context.Main.Temperature, 1)&nbsp;°C</strong>
</CustomTemplate>
</WeatherWidget>
@using Blazor.WeatherWidget.Services;
@using Blazor.WeatherWidget.Models;
@inject IWeatherService service;
<!-- That's our default tempate -->
@{
RenderFragment defaultTemplate =
@<div>
@if (result != null)
{
<div>@Math.Round(result.Main.Temperature, 1)&nbsp;°C</div>
<!-- Add an input that is bound to the new property CurrentCity -->
<input value="@CurrentCity" @oninput="@((e) => { CurrentCity = (string)e.Value; })">
<!-- Add a button that onclick runs an event to retrieve data for the typed city -->
<button class="btn btn-info" type="button" @onclick="OnSearchNewCity">Go!</button>
}
</div>; <!-- Mind the semicolon here, it marks the end of our template! -->
}
@if (result == null)
{
//We can define a new template for loading too!
<p><em>Loading...</em></p>
}
else
{
//If dev didnt define one, lets use ours
if (CustomTemplate == null)
{
@defaultTemplate
}
else
{
@CustomTemplate(result);
}
}
@code {
private Root result;
//A public parameter, exactly as we did with the CurrentCity parameter
[Parameter]
public RenderFragment<Root> CustomTemplate { get; set; }
[Parameter]
public string CurrentCity { get; set; } = "Munich, DE";
[Parameter]
//This provides support for two-way binding from parent component e.g. <WeatherWidget @bind-CurrentCity="@currentCity" />
public EventCallback<string> CurrentCityChanged { get; set; }
protected override async Task OnParametersSetAsync()
{
await PopulateWeatherDataAsync();
}
protected async Task OnSearchNewCity()
{
await PopulateWeatherDataAsync();
}
private async Task PopulateWeatherDataAsync()
{
result = await service.Get(CurrentCity, "XXXXXXXXXXXXXXXXXXXXXXX");
}
}
@page "/"
@using Blazor.WeatherWidget
<!-- Showing weather with the default template -->
<WeatherWidget CurrentCity="London, UK" />
<br /><br /><br />
<!-- Using a custom template -->
<WeatherWidget @bind-CurrentCity="@myCityBinding">
<CustomTemplate>
That's the temperature in @myCityBinding: <strong>@Math.Round(context.Main.Temperature, 1)&nbsp;°C</strong>
<br />
<input value="@myCity" @oninput="@((e) => { myCity = (string)e.Value; })">
<button class="btn btn-info" type="button" @onclick="OnSearchNewCity">Search for a new temperature!</button>
</CustomTemplate>
</WeatherWidget>
@code {
private string myCity = "Tokyo";
private string myCityBinding = "Tokyo";
protected void OnSearchNewCity()
{
myCityBinding = myCity;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment