View a Saved Order
Introduction
We have reached the stage when we can add a new order, and make changes to order lines in the process, but having saved the order we cannot make further changes - or even view it! In this post we take the first steps in viewing and editing an order
Viewing an Order
The first thing we must do is make the 'Edit' button on the Purchase Orders list do something. Luckily, this is fairly straightforward; we simply have to amend the ToolbarClickHandler in the Index.razor to pass the POHeaderID to PurchaseOrderPage.razor when it opens. But before we can do that we need to establish which order the user has selected and warn them if no order has been selected.
We'll start by adding the 'RowSelectHandler' and changing the <GridEvents> to include it.
Add the following to the end of the code section to identify the row clicked by the user:
public void RowSelectHandler(RowSelectEventArgs<POHeader> args)
{
//{args.Data} returns the current selected records.
selectedPOHeaderID = args.Data.POHeaderID;
}And declare 'selectedPOHeaderID' in the code section:
private int selectedPOHeaderID { get; set; } = 0;And amend the <GridEvents> tag withing the html section.
<GridEvents RowSelected="RowSelectHandler" OnToolbarClick="ToolbarClickHandler" TValue="POHeader"></GridEvents>If the user doesn't click on a row we can re-use the Warning Blazor component and pass a suitable message to it.
Paste the following at the foot of the html section to display the Warning component.
<WarningPage @ref="Warning" WarningHeaderMessage="@WarningHeaderMessage" WarningContentMessage="@WarningContentMessage" />To be able to use this we need to declare the component and the strings being passed to it. At a suitable position near the top of the code section paste the following:
WarningPage Warning;
string WarningHeaderMessage = "";
string WarningContentMessage = "";Having set up everything, the code to open PurchaseOrderPage with the selected order is achieved by adding the following to the ToolbarClickHandler for the 'Edit' button.
//Code for editing - Check that an Order has been selected from the grid
if (selectedPOHeaderID == 0)
{
WarningHeaderMessage = "Warning!";
WarningContentMessage = "Please select an Order from the grid.";
Warning.OpenDialog();
}
else
{
NavigationManager.NavigateTo($"/purchaseorder/{selectedPOHeaderID}");
}It checks that a row has been selected, and if so uses NavigationManager to open the PurchaseOrderPage (/purchaseorder) for the selected order, otherwise pops up the Warning message.
Having made these changes and running the code is a little disappointing...
It has 'Edit an Order' as a title, but doesn't show the order! The reason for this is that the data for the 'header' part of the form comes from the 'orderaddedit' model and this is empty. Furthermore the data source for the 'order lines' grid is 'orderLines' and this too is empty.
Looking at these omissions, the two datasources need to be populated when the page is initialised. The first of these can easily be remedied by placing the following code in the OnInitializedAsync method immediately below 'pagetitle = "Edit an Order;"'. It uses the 'GetOne' service, passing to it the POHeaderID.
orderaddedit = await POHeaderService.POHeader_GetOne(POHeaderID);Populating the order lines grid poses a bit more of a problem. We cannot use the generic 'POLineList' service as this will get all order lines. We want the order lines for the current order. This will mean a new SQL stored procedure, and changes to POLineService and IPOLineService.
Open SQL Management Studio, select the PurchaseOrders database, Programmability, StoredProcedures. We can use the existing POLine_GetOne as a model, changing the parameter from POLineID to POLineHeaderID and the name of the procedure to spPOLine_GetByPOHeader, as shown in the code below. Open a new query and paste the code and execute the query.
USE [PurchaseOrders]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-------------- Stored Proc for SELECT (by POHeaderID)
CREATE PROCEDURE [dbo].[spPOLine_GetByPOHeader]
-- Needs one parameter HeaderID
@POHeaderID int
AS
BEGIN
-- SQL Select
SELECT POLineID, POLineHeaderID, POLineProductID, POLineProductDescription, POLineProductQuantity,
POLineProductUnitPrice, POLineTaxRate
FROM POLine WHERE POLineHeaderID= @POHeaderID
END
GO
Similarly, we need to add a new method to POLineService which we will call POLineGetByPOHeader. Open POLineService and copy and paste the code shown below. As can be seen it is a bit of an amalgam of the existing POLine_GetOne and POLineList methods.
public async Task<IEnumerable<POLine>> POLine_GetByPOHeader(int @POHeaderID)
{
IEnumerable<POLine> polines;
var parameters = new DynamicParameters();
parameters.Add("@POHeaderID", POHeaderID, DbType.Int32);
using (var conn = new SqlConnection(_configuration.Value))
{
polines = await conn.QueryAsync<POLine>("spPOLine_GetByPOHeader", parameters, commandType: CommandType.StoredProcedure);
}
return polines;
}
We now need to add the service to the interface. Insert the following line into IPOLineService.cs. Note the parameter.
Task<IEnumerable<POLine>> POLine_GetByPOHeader(int @POHeaderI);To complete this, return to PurchaseOrderPage.razor and declare the new IEnumerable by pasting the following at the top of the code section. I suggest placing it immediately under the other IEnumerables. Note that I have called it 'orderLinesByPOHeader' - I cannot use 'orderLines' as that is already declared as a List
IEnumerable<POLine> orderLinesByPOHeader;Add these three lines to the OnInitializeAsync under the existing code for 'Edit and Order'. The first line populates orderLinesByPOHeader, the second converts the IEnumerable into a list and the third prevents the user from changing the supplier. (We need this because some of the products could well be specific to the original supplier.)
orderLinesByPOHeader = await POLineService.POLine_GetByPOHeader(POHeaderID);
orderLines = orderLinesByPOHeader.ToList(); //Convert from IEnumable to List
supplierEnabled = false;Save and run the project.
It's better than we had before, but the order lines aren't showing all the data we want or need.
The Product Code is not being displayed because although the POLine model in the project contains the ProductCode column it is not saved to the SQL database, it is derived from the Product table; similarly the NetPrice, TaxAmount and GrossAmount are calculated columns and are not being returned by the POLines_GetByPOHeader we are using to populate 'orderLines'.
All these deficiencies can be solved by amending the SQL stored procedure used to get the data.
Open SQL Management Studio and modify the POLines_GetByPOHeader as shown below:
USE [PurchaseOrders]
GO
DROP PROCEDURE [dbo].[spPOLine_GetByPOHeader]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-------------- Stored Proc for SELECT by POHeader, with Product Code and Net, Tax and Gross
CREATE PROCEDURE [dbo].[spPOLine_GetByPOHeader]
--
@POHeaderID int
AS
BEGIN
-- SQL Select for one table row
SELECT dbo.POLine.POLineID, dbo.POLine.POLineHeaderID, dbo.POLine.POLineProductID, dbo.Product.ProductCode as POLineProductCode,
dbo.POLine.POLineProductDescription, dbo.POLine.POLineProductQuantity, dbo.POLine.POLineProductUnitPrice,
dbo.POLine.POLineProductUnitPrice * dbo.POLine.POLineProductQuantity AS POLineNetPrice,
dbo.POLine.POLineTaxRate,
dbo.POLine.POLineProductUnitPrice * dbo.POLine.POLineProductQuantity * dbo.POLine.POLineTaxRate AS POLineTaxAmount,
(dbo.POLine.POLineProductUnitPrice * dbo.POLine.POLineProductQuantity) * (1 + dbo.POLine.POLineTaxRate) AS POLineGrossPrice
FROM dbo.POLine INNER JOIN
dbo.Product ON dbo.POLine.POLineProductID = dbo.Product.ProductID
WHERE POLineHeaderID= @POHeaderID
END
GOThe important lines are pointed out in this screen-shot
Save and run the project. Select an order from the Purchase Order List and click 'Edit'. The data should be displayed as shown below. However, you won't be able to save and changes despite the appearance that you have made changes.
Project Code
The code for the files changed in this post are shown here.
YouTube Video
Blazor Purchase Orders - Part 16 - View a Saved Order



