Grid column template with select2

I have a grid column like
```

<GridColumn Field=@nameof(SchoolDto.DepartmentNumber) HeaderText="Department #">
     <EditTemplate>
         @{
             var school = (context as SchoolDto);
             <select class="form-select select2-departmentnumber" aria-required="true"
                     data-placeholder="-- Select DepartmentNumber --">
                     @if (school!.DepartmentNumber > 0)
                     {
                         <option value="@school!.DepartmentNumber" selected="selected">@school!.DepartmentNumber</option>
                     }
             </select>
         }
     </EditTemplate>
 </GridColumn>

```
How would I bind the value selected in the select to school.DepartmentNumber.
Also I want this to be a select2. The problem is that on page load the select is not in the DOM so calling any JS will not detect it.  The select only appears on editing.  When would be a good time to call the JS to turn the select into a select2.  In which event.


14 Replies

PS Prathap Senthil Syncfusion Team March 25, 2024 12:50 PM UTC

Hi Wuss,

Based on the reported problem, we would like to clarify that the grid edit template feature will be performed when a row is in editing state. This is the default behavior. If you want to call a function at the appropriate time in JavaScript, we suggest using the Databound event to achieve your requirement. Alternatively, if you want to perform the same operation during initialization, we suggest using the Column template feature to apply the same code as you did in the edit template to achieve your requirement.


Regards,
Prathap S



WW Wuss Wuzz March 25, 2024 02:55 PM UTC

Thanks for your reply.  I was able to solve the 2nd part of the issue by running a JS script each time "BeginEdit" and "Add" action were fired in "OnGridActionBegin". The JS started a "MutationObserver" that watched for the appearance of the "select" and applied the "select2" features to it when it became available.

I am still having an issue with Part1 of the question binding

 <GridColumn Field=@nameof(SchoolDto.DepartmentNumber) HeaderText="Department #">
     <EditTemplate>
         <select @bind="((context as SchoolDto)!.DepartmentNumber)" class="form-select select2-departmentnumber" aria-required="true"
                 data-placeholder="-- Select Department # --">
             @if (context is not null && (context as SchoolDto).DepartmentNumber > 0)
             {
                 <option value="@((context as SchoolDto).DepartmentNumber)" selected="selected">
                     @((context as SchoolDto).DepartmentNumber)
                 </option>
             }
         </select>
     </EditTemplate>
 </GridColumn>

When i try to bind to the context the original value in that field is retained it does not update to the value i selected in the select. That is for updating.  If I add it says no value was selected as i have that field as a required field.  I can see the value visually was selected but for some reason it thinks no value is there.



PS Prathap Senthil Syncfusion Team March 26, 2024 11:45 AM UTC

Before proceeding with the reporting of the problem, we require some additional clarification from your end. Please share the following details to proceed further on our end:

  • To analyze the reported issue, could you please share a simple and reproducible sample with duplicate data that demonstrates the problem? This will assist us in identifying the issue more efficiently and providing a resolution.
  • Could you please share the which NuGet version you have used,

The details requested above will be very helpful in validating the reported query on our end and providing a solution as soon as possible. Thanks for your understanding.


Additionally, we have support for the Syncfusion dropdown component using the in-grid edit template. Please refer to this documentation for more information.




WW Wuss Wuzz March 26, 2024 05:26 PM UTC

Hi there, I have attached a demo. I took the liberty of adding two more more issues that I would have posted separately in the demo.

#1
Launch project and navigate to Products link. The grid will load. Try to add a product. It's not possible.
Try to edit a product by changing the category. After record is saved it saves with old value and not new value.

#2
On the same product pages The category Id is displayed instead of the category name. Seems I can't use Navigation property in the grid column?

#3
Open the category page and you will see that it results in a 401 when using webapi adaptor. The route it is trying to access has an [Authorize] annotation.  Auth/Authz is done with built in identity cookies.  It's difficult to find how to set up with the grid to send cookies.

Nuget Packages

<PackageReference Include="Syncfusion.Blazor.Grid" Version="25.1.35" />
<PackageReference Include="Syncfusion.Blazor.Themes" Version="25.1.35" />


Thanks.


Attachment: DemoAuth_a408a3f8.zip



PS Prathap Senthil Syncfusion Team April 1, 2024 02:18 PM UTC

Regarding the first query, it appears that the primary key is not provided when performing the add operation. The CRUD operation requires the presence of a primary key to execute. Therefore, please ensure that the primary key is included when inserting records. Refer the below code snippet and documentation for your reference,

      <GridColumn Field=@nameof(Product.Id) HeaderText="Id" IsPrimaryKey="true" Visible="true" />



Note: If you wish to hide the primary key column, please enable the 'IsIdentify' property in the grid column and ensure the same on the database side. Refer to the documentation provided for further details.
API Link: https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.GridColumn.html#Syncfusion_Blazor_Grids_GridColumn_IsIdentity



Regarding the second query, it seems that you have bound the category ID, and the grid displays based on the field property defined in the grid column. This behavior is default for the grid. If you wish to display the category name using the column template feature to meet your requirements, you can achieve this by referring to the code snippet below. Similar to this example, you can customize the behavior to meet your specific needs.

<Template>

     @{

         var data = context as Product;

         if(data.CategoryId == 1)

         {

             <span>Electronics</span>

         }

         if (data.CategoryId == 2)

         {

             <span>Clothing</span>

         }

         if (data.CategoryId == 3)

         {

             <span>Produce</span>

         }

 

     }

</Template>


Regarding the third query, we have already documented the scenario. Kindly refer to the documentation below for your reference.

https://blazor.syncfusion.com/documentation/datagrid/data-binding#authorization-and-authentication



WW Wuss Wuzz April 1, 2024 05:32 PM UTC

I figured out #2 above. I just needed to use "Field="NavigationProperty.Property" instead of "Field=@nameof(Value.NavigationProperty.Property)" in my specific case

<GridColumn Field="Category.Name" HeaderText="Category">


#1 enabling IsIdentity does not work, I believe I already had IsPrimaryKey enabled, and even making it visible did not work.  Did you try it from your end and it worked?

#3 still an issue as your documentation refers to bearer tokens, I am using the default Identity cookies for auth/authz. Is that supported?



PS Prathap Senthil Syncfusion Team April 4, 2024 11:37 AM UTC

Regarding the issue with the add operation, we suggest using the AutoComplete component according to your requirements. This will facilitate achieving your desired functionality with proper add operations in the grid. Please refer to the modified code snippet and sample provided below for your reference.

<GridColumn Field=@nameof(Product.CategoryId) HeaderText="Category">

 

                 

     <EditTemplate>

         <SfAutoComplete ID="CategoryId"  Placeholder="Select Category please type number" TItem="Category" TValue="int" @bind-Value="@((context as Product).CategoryId)" DataSource="@Categories">

             <AutoCompleteFieldSettings Value="id" Text="Name"></AutoCompleteFieldSettings>

         </SfAutoComplete>

         </EditTemplate>

</GridColumn>


Are you experiencing any issues with bearer tokens? Could you please share with us the specific problem you encountered with the replication sample.


Attachment: DemoAuth_2f105515.zip


WW Wuss Wuzz April 5, 2024 01:51 PM UTC

1.
"we suggest using the AutoComplete component according to your requirements."
The reason I selected Select2 is that it supports filter and paging (not virtualization) from the server side. 
That is as  you type or scroll it fetches a set amount from the server directly without downloading the entire table.

Is this supported in sfautocomplete or sfdropdownlist, I could not find any documentation to let me know this. Serverside paging and filtering are the requirements here.

2.
The application is using cookies for authentication.  To introduce bearer tokens would mean having two different auth mechanisms. Does it mean I have to strip out cookies auth and replace with a bearer token type of auth?



WW Wuss Wuzz April 8, 2024 09:04 PM UTC

I have set up a JS action to read the current select2 value

and this additional grid action


    private async void OnGridActionBegin(ActionEventArgs<SchoolDto> args)
    {
        if (args.RequestType.Equals(Syncfusion.Blazor.Grids.Action.Save))
        {
            var select2Selection = await _jsruntime.InvokeAsync<string>("blazorInterop.Select2GetValue",
            "select2-departmentnumber");
            if (int.TryParse(select2Selection, out int departmentNumber))
            {
                args.Data = args.Data with { DepartmentNumber = departmentNumber };
                Console.WriteLine(args.Data);
            }
        }
    }

I can see the correct currently selected value is retireved and I can see that the object is correctly updated in the action, But it is being done AFTER sending the request to update the info. I can't tell where would be the proper place to update args.Data before request is sent to update grid.  I thought it would be in the save action.

It seems having an await statement in the OnActionBegin handler when a save occurs is not waiting on the await, but instead proceeding to send the request.  It seems like a bug.



PS Prathap Senthil Syncfusion Team April 10, 2024 12:48 PM UTC

1.Yes, you can filter the data from the server side by changing the query property dynamically when using remote data, or else manually request the server when custom filtering is used. Can you please share the use case scenario for paging support and specify whether you want a remote datasource or local datasource?"
Reference: Syncfusion documentation on Autocomplete virtualization

2.Yes, migrating to bearer tokens entails replacing cookie-based authentication with a token-based system, consolidating authentication mechanisms.

Regarding your last update, we suggest resolving this problem by using Async Task


    private async Task OnGridActionBegin(ActionEventArgs<SchoolDto> args)
    {
        if(args.RequestType.Equals(Syncfusion.Blazor.Grids.Action.Save))
        {
            var select2Selection =await _jsruntime.InvokeAsync<string>("blazorInterop.Select2GetValue",
            "select2-departmentnumber");
            if(int.TryParse(select2Selection,outint departmentNumber))
            {
                args.Data= args.Datawith{DepartmentNumber= departmentNumber };
                Console.WriteLine(args.Data);
            }
        }
    }
 


WW Wuss Wuzz April 10, 2024 02:25 PM UTC

Wow regarding the async bit I forgot to change the void to Task that you pointed out above! THANK YOU!



MS Monisha Saravanan Syncfusion Team April 11, 2024 06:32 AM UTC

We are glad to hear that the reported issue resolved at your end. Kindly get back to us if you have further queries. As always we will be happy to assist you.



WW Wuss Wuzz April 27, 2024 01:14 PM UTC

Finally figured out how to make syncfucion grid work with auth cookies.

if using blazor .net8 or greater , I did this


...
...


builder.Services.AddHttpClient(
    "MyApp",
    client => client.BaseAddress = new Uri(builder.Configuration.GetSection("AppUrls")["BaseApiUrl"]!)
).AddHeaderPropagation() // <--- THIS LINE MUST BE ADDED

.ConfigurePrimaryHttpMessageHandler(() =>
{
    // !!! DISABLE IN PROD. THIS IS TO BYPASS CHECKING SSL CERT AUTH FOR DEV PURPOSES !!!
    var handler = new HttpClientHandler
    {
        ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
    };


    return handler;
});
builder.Services.AddHeaderPropagation(options => // <-- THIS BLOCK MUST BE ADDED

{
    options.Headers.Add("Cookie");  <--- THE HEADER FOR ME WAS "Cookie"

});


...
...


app.UseHttpsRedirection();
app.UseHeaderPropagation(); //<--- MUST BE ADDED, place after app.UseHttpsRedirection()


...
...





PS Prathap Senthil Syncfusion Team April 29, 2024 11:34 AM UTC

Thanks for the update,


We are happy to hear that the issue you reported has been resolved at your end. We are closing the thread now.


Loader.
Up arrow icon