I want to create a custom dialog to create a product and update it. But I don't understand how I can pass the required data type to CustomAdaptor
What I'm doing now:
My Blazor page:
<div class="container">
<div class="row d-flex flex-direction-column justify-content-end">
<div class="col-10 mt-5">
<SfGrid TValue="ProductDto"
AllowPaging="true"
AllowSorting="true"
AllowResizing="true"
ShowColumnChooser="true"
AllowFiltering="true"
@ref="Grid"
Toolbar="@ToolbarItems"
Query="@Query">
<SfToolbar>
<ToolbarItems>
<ToolbarItem Type="ItemType.Input">
<Template>
<SfDropDownList Placeholder="@Loc["SelectLanguageForDataGridText"]"
TValue="int"
TItem="LanguageSelector"
DataSource="@AvailabelLanguages"
Value="@SelectedLanguage.Code"
Width="200"
FloatLabelType="Syncfusion.Blazor.Inputs.FloatLabelType.Always">
<DropDownListFieldSettings Text="Text" Value="Code"></DropDownListFieldSettings>
<DropDownListEvents TValue="int" TItem="LanguageSelector" ValueChange="OnChange"></DropDownListEvents>
</SfDropDownList>
</Template>
</ToolbarItem>
</ToolbarItems>
</SfToolbar>
<SfDataManager @ref="dataManager" Adaptor="Adaptors.CustomAdaptor" AdaptorInstance="typeof(ProductAdaptor)"></SfDataManager>
<GridEvents OnActionFailure="OnActionFailureHandler" OnActionBegin="OnActionBeginHandler" TValue="ProductDto"></GridEvents>
<GridPageSettings PageSizes="true"
PageSize="20">
</GridPageSettings>
<GridEditSettings AllowAdding="true"
AllowDeleting="true"
AllowEditing="true"
Mode="EditMode.Dialog">
<Template Context="context">
@{
if (CurrentAction == Syncfusion.Blazor.Grids.Action.Add)
{
var item = new CreateProductDto();
<div class="col-12">
<div class="form-row d-flex align-items-center gap-3">
<div class="form-group col-md-6">
<SfTextBox
@bind-Value="item.Name"
Placeholder="@($"{Loc["NameText"].Value} Ru")"
FloatLabelType="FloatLabelType.Auto">
</SfTextBox>
</div>
<div class="form-group col-md-6">
<SfTextArea
ColumnCount="100"
@bind-Value="item.Description"
Placeholder="@($"{Loc["DescriptionText"].Value} Ru")"
FloatLabelType="FloatLabelType.Auto">
</SfTextArea>
</div>
</div>
<div class="form-row d-flex align-items-center gap-3">
<div class="form-group col-md-6">
<SfTextArea
@bind-Value="item.ShortDescription"
Placeholder="@($"{Loc["ShirtText"].Value} Ru")"
FloatLabelType="FloatLabelType.Auto">
</SfTextArea>
</div>
<div class="form-group col-md-6">
<SfTextArea
ColumnCount="100"
@bind-Value="item.ImageUrls"
Placeholder="@($"{Loc["EnterImageUrlsText"].Value}")"
FloatLabelType="FloatLabelType.Auto">
</SfTextArea>
</div>
</div>
<div class="form-row d-flex align-items-center gap-3">
<div class="form-group col-md-3">
<SfTextBox
@bind-Value="item.DarwinArticleNumber"
Placeholder="@($"{Loc["EnterStoreArticleText"].Value} Darwin")"
FloatLabelType="FloatLabelType.Auto">
</SfTextBox>
</div>
<div class="form-group col-md-3">
<SfTextBox
@bind-Value="item.EnterArticleNumber"
Placeholder="@($"{Loc["EnterStoreArticleText"].Value} Enter")"
FloatLabelType="FloatLabelType.Auto">
</SfTextBox>
</div>
<div class="form-group col-md-3">
<SfTextBox
@bind-Value="item.CactusArticleNumber"
Placeholder="@($"{Loc["EnterStoreArticleText"].Value} Cactus")"
FloatLabelType="FloatLabelType.Auto">
</SfTextBox>
</div>
<div class="form-group col-md-3">
<SfTextBox CssClass="name-cell"
@bind-Value="item.UltraArticleNumber"
Placeholder="@($"{Loc["EnterStoreArticleText"].Value} Ultra")"
FloatLabelType="FloatLabelType.Auto">
</SfTextBox>
</div>
</div>
<div class="form-row d-flex align-items-center gap-3">
<div class="form-group col-md-3">
<SfDropDownList Placeholder="@Loc["SelectCategoryForDataGridText"]"
TValue="int"
TItem="CategoryDropDownModel"
DataSource="@CategoriesDropDownModel"
Value="@item.CategoryId"
Width="200"
FloatLabelType="Syncfusion.Blazor.Inputs.FloatLabelType.Always">
<DropDownListFieldSettings Text="Name" Value="Id"></DropDownListFieldSettings>
<DropDownListEvents TValue="int" TItem="CategoryDropDownModel"></DropDownListEvents>
</SfDropDownList>
</div>
</div>
</div>
}
}
</Template>
</GridEditSettings>
<GridColumns>
<GridColumn Field="@nameof(ProductDto.Id)"
HeaderText="Id"
AllowAdding="false"
AllowEditing="false"
IsPrimaryKey="true" />
<GridColumn Field="@nameof(ProductDto.Name)"
HeaderText="@($"{Loc["NameText"].Value}")" />
<GridColumn Field="@nameof(ProductDto.Description)"
HeaderText="@($"{Loc["DescriptionText"].Value}")" />
<GridColumn Field="@nameof(ProductDto.ShortDescription)"
HeaderText="@($"{Loc["ShortDescriptionText"].Value}")" />
<GridColumn Field="@nameof(ProductDto.DarwinArticleNumber)"
HeaderText="@($"Darwin {Loc["ArticleText"].Value}")" />
<GridColumn Field="@nameof(ProductDto.EnterArticleNumber)"
HeaderText="@($"Enter {Loc["ArticleText"].Value}")" />
<GridColumn Field="@nameof(ProductDto.UltraArticleNumber)"
HeaderText="@($"Ultra {Loc["ArticleText"].Value}")" />
<GridColumn Field="@nameof(ProductDto.CactusArticleNumber)"
HeaderText="@($"Cactus {Loc["ArticleText"].Value}")" />
<GridColumn Field="@nameof(ProductDto.CreatedAt)"
HeaderText="@Loc["CreatedAtText"].Value"
Format="d"
Type="ColumnType.Date"
AllowAdding="false"
AllowEditing="false" />
<GridColumn Field="@nameof(ProductDto.UpdatedAt)"
Visible="false"
HeaderText="@Loc["UpdatedAtText"].Value"
Format="d"
Type="ColumnType.Date"
AllowAdding="false"
AllowEditing="false" />
<GridColumn Field="@nameof(ProductDto.CreatedBy)"
Visible="false"
HeaderText="@Loc["CreatedByText"].Value"
AllowEditing="false" />
</GridColumns>
</SfGrid>
</div>
</div>
</div>
My adaptor:
using Newtonsoft.Json;
using PriceScout.Shared.DTOs.Categories;
using PriceScout.Shared.DTOs.Common;
using Syncfusion.Blazor.Data;
using Syncfusion.Blazor;
using System.Net.Http.Json;
using PriceScout.Shared.DTOs;
using PriceScout.Shared.DTOs.Products;
namespace PriceScout.Client.Adaptors
{
public class ProductAdaptor : DataAdaptor
{
private readonly HttpClient _httpClient;
private readonly IConfiguration _configuration;
public ProductAdaptor(HttpClient httpClient, IConfiguration configuration)
{
_httpClient = httpClient;
_configuration = configuration;
}
public async override Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string additionalParam = null)
{
var skip = dataManagerRequest.Skip;
var take = dataManagerRequest.Take;
var pageIndex = skip / take;
int language = 1;
if(dataManagerRequest.Params is not null && dataManagerRequest.Params["LanguageCode"] is not null)
{
language = (int)dataManagerRequest.Params["LanguageCode"];
}
var response = await _httpClient.GetAsync(
_configuration["GatewayUrl"] +
$"/api/products/all?language={language}&PageSize={take}&PageIndex={pageIndex}&isDelete=false&getAllRows=false");
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Status Code: {response.StatusCode}. Error:{await response.Content.ReadAsStringAsync()}");
}
var result = JsonConvert.DeserializeObject<PaginationResponseDto<ProductDto>>(await response.Content.ReadAsStringAsync());
DataResult dataResult = new DataResult
{
Result = result.Items,
Count = result.Totaltems,
};
return dataResult;
}
public async override Task<object> InsertAsync(DataManager dataManager, object record, string additionalParam)
{
CreateProductDto product = record as CreateProductDto;
var response = await _httpClient.PostAsJsonAsync(_configuration["GatewayUrl"] + "/api/products/", product);
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Status Code: {response.StatusCode}. Error:{await response.Content.ReadAsStringAsync()}");
}
return record;
}
public async override Task<object> RemoveAsync(DataManager dataManager, object primaryColumnValue, string primaryColumnName, string additionalParam)
{
var response = await _httpClient.DeleteAsync(_configuration["GatewayUrl"] + $"/api/products/{primaryColumnValue}");
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Status Code: {response.StatusCode}. Error:{await response.Content.ReadAsStringAsync()}");
}
return primaryColumnValue;
}
public async override Task<object> UpdateAsync(DataManager dataManager, object record, string primaryColumnName, string additionalParam)
{
var product = record as UpdateProductDto;
var response = await _httpClient.PutAsJsonAsync(_configuration["GatewayUrl"] + "/api/products/", product);
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Status Code: {response.StatusCode}. Error:{await response.Content.ReadAsStringAsync()}");
}
return record;
}
}
}
For example, how can I pass an object of type CreateProductDto to InsertAsync and an object of type UpdateProductDto to UpdateAsync?
Hi
RTi Developer,
Based on your query, it seems that you want to use different class names for
add and update operations. We would like to clarify that the CRUD operations
will work based on the grid's TValue = "ProductDto" as the model
type. Using different contexts is not feasible when performing CRUD operations.
Please note that our Grid component requires strongly-typed objects or POCO (Plain Old CLR Object) types for data binding. This means that data binding must be based on a specific model type (class) with strongly-typed properties. This behavior is inherent to the default functionality of the Grid. If the model type is unknown, we recommend using ExpandoObjectBinding or DynamicObjectBinding. For more information about these binding options, please refer to the following documentation link
https://blazor.syncfusion.com/documentation/datagrid/columns#expandoobject-complex-data-binding
https://blazor.syncfusion.com/documentation/datagrid/columns#dynamicobject-complex-data-binding
Regards,
Prathap Senthil