Countries & Cities - Part 1

The objective for the Countries & Cities page is to have a drop-down list of countries at the top of the page, and once the user has selected a country to show cities for that country with their population.  The user will be able to add, edit and delete cities for the chosen country.

As with the Countries page, we will take this step by step.  However, unlike Countries the add and edit will be accomplished without the need to use a separate page.

Cities Blazor Component

Add a new Blazor component, call it 'CountriesAndCities.razor' and replace all existing code with the following:

@page "/countriesandcities"
@using BlazorCountries.Data
@inject ICountriesService CountriesService
@inject ICitiesService CitiesService

<h3>Countries and Cities</h3>

The page routing will be '/countiesandcities', and as we will be using data from both countries and cities both services are injected.

As a bit of a diversion, we will now change the default menu that comes with a Blazor application so that we can access our new page.  In Solution Explorer, expand the Shared folder and open NavMenu.razor.  Just a few changes here:

  • On the second line insert a space between Blazor and Countries.  (Visual Studio created the name from the project name.)
  • On line 12 replace 'Home' with 'Countries'.
  • On line 16 change the href= from to 'counter' to 'countriesandcities' (the routing)
  • On line 16 change 'Counter' to 'Cities'
  • Delete the last <li></li> section (lines 20 to 24) as this is not needed.

Adding the Countries Drop Down List

Add the following code under the existing code of 'CountriesAndCities.razor'.

<SfDropDownList TItem="Countries"
                TValue="string"
                DataSource="@countries"
                Placeholder="Select a country">
    <DropDownListFieldSettings Text="CountryName" Value="CountryId"></DropDownListFieldSettings>
</SfDropDownList>

@code{
    IEnumerable<Countries> countries;

    protected override async Task OnInitializedAsync()
    {
        //Populate the list of countries objects from the Countries table.
        countries = await CountriesService.CountriesGetAll();
    }
}

We are using the Syncfusion SfDropDownList.  This takes two properties, TItem, the data source type and TValue, the dropdown value list type.  In this case TItem is set to '"Countries" and TValue to "String".  Also specified is the DataSource and a suitable placeholder.

<DropDownListFieldSettings> has two settings, Text, the name of the field in the data source to be displayed (CountryName) and Value, the name of the field to be used as the key to the data.

Within the '@code' section 'countries' is declared as an IEnumerable and the OnInitializedAsync() function used to populate 'countries'.  This is just about the minimum needed to display the dropdown list.

By default the dropdown list occupies the input element's width with a height of 350px.  These can be adjusted by adding 'PopupHeight' and 'PopupWidth' properties within the <SfDropdownList> tag.

<SfDropDownList TItem="Countries"
                TValue="string"
                DataSource="@countries"
                Placeholder="Select a country"
                PopupHeight="200px"
                PopupWidth="250px">
    <DropDownListFieldSettings Text="CountryName" Value="CountryId"></DropDownListFieldSettings>
</SfDropDownList>

However, as can be seen from the screenshot, this only controls the height and width of the drop-down, not the width of the drop down list field.  If we want to control how this is displayed we need to use some css (Cascading Style Sheet).  As with C# I'm a bit of a novice with css, but the following works in this situation.

  • Add a <div></div> around the whole dropdown list and give it class name of 'control_wrapper' (it could be anything), and add the following css between the HTML and Code sections.
<style>
    .control_wrapper {
        width: 250px;
    }

The code, and the result of running the application, at this stage should be as below.  Note that the style width is 250px, the same as the PopupWidth.

Adding a Datagrid for Cities

Under the dropdown list for countries we will add a datagrid to show the cities for the selected country.  To add the datagrid, add the following code in the HTML section of the page.

<div>
        <SfGrid ID="CityGrid"
                DataSource="@cities"
                AllowSorting="true"
                AllowResizing="true"
                Height="200">

            <GridColumns>
                <GridColumn Field="@nameof(Cities.CityName)"
                            HeaderText="City Name"
                            TextAlign="@TextAlign.Left"
                            Width="50">
                </GridColumn>
                <GridColumn Field="@nameof(Cities.CityPopulation)"
                            HeaderText="Population"
                            Format="n"
                            TextAlign="@TextAlign.Right"
                            Width="50">
                </GridColumn>
            </GridColumns>
        </SfGrid
</div>

The above follows the pattern used for the Countries datagrid.  It is wrapped by <div> tags, and the data source is '@cities'; there are two columns, one for the name of the city and the other for the population.  The column for population has an attribute of 'Format="n"' which will display the population with thousands comma separators but no decimal places.

We need to add the code to define the @cities datasource.  To do this add the following to the code section, immediately under the equivalent line for countries.

IEnumerable<Cities> cities;

We have no data for cities, and there is no connection between the Countries dropdown list and cities datagrid yet, but save all files and run the application.  It should build without errors and show the following:

The next stage is to link the Countries dropdown with the grid and create a mechanism to allow the user to add cities. 

YouTube Video

Blazor + Syncfusion + Dapper: Part 7