Hi,
In your QueryBuilder documentation for "Value template", the code sample has this:
... but when it runs, the value in the QueryBuilder isn't 'Debit Card', it's "Cash". This is even demonstrated by the image following that code in the documentation:
Can you tell me how to use a Dropdown value template in such a way that it's updated correctly when the rules are set/changed?
Further, it seems strange to bind the value from the template directly to a single property of the component, because surely the dropdown could appear multiple times, in different rules?
@using Syncfusion.Blazor.QueryBuilder
@using Syncfusion.Blazor.DropDowns
<div class="col-lg-12 control-section">
<SfQueryBuilder TValue="ExpenseData" Width="100%" DataSource="@DataSource">
<QueryBuilderRule Condition="and" Rules="@Rules"></QueryBuilderRule>
<QueryBuilderColumns>
<QueryBuilderColumn Field="PaymentMode" Label="PaymentMode" Type=Syncfusion.Blazor.QueryBuilder.ColumnType.String>
<QueryBuilderTemplates>
<ValueTemplate>
<SfDropDownList TValue="string" TItem="ItemFields" DataSource="@Items" @bind-Value="@DefaultValue">
<DropDownListFieldSettings Text="Id"></DropDownListFieldSettings>
<DropDownListEvents TItem="ItemFields" TValue="string" ValueChange="e => OnChange(e, context)"></DropDownListEvents>
</SfDropDownList>
</ValueTemplate>
</QueryBuilderTemplates>
</QueryBuilderColumn>
<QueryBuilderColumn Field="Category" Label="Category" Type=Syncfusion.Blazor.QueryBuilder.ColumnType.String></QueryBuilderColumn>
<QueryBuilderColumn Field="Description" Label="Description" Type=ColumnType.String></QueryBuilderColumn>
<QueryBuilderColumn Field="Amount" Label="Amount" Type=Syncfusion.Blazor.QueryBuilder.ColumnType.Number></QueryBuilderColumn>
</QueryBuilderColumns>
</SfQueryBuilder>
</div>
@code{
public string DefaultValue = "Cash";
public List<ExpenseData> DataSource;
public class ExpenseData
{
public string Category { get; set; }
public string PaymentMode { get; set; }
public string Description { get; set; }
public int Amount { get; set; }
}
protected override void OnInitialized()
{
DataSource = new List<ExpenseData>()
{
new ExpenseData() {Category= "Food", PaymentMode="Credit Card", Description="Boiled peanuts", Amount=100 },
new ExpenseData() {Category= "Food", PaymentMode="Debit Card", Description="Boiled peanuts", Amount=200 },
new ExpenseData() {Category= "Food", PaymentMode="Cash", Description="Confederate cush", Amount=300 },
new ExpenseData() {Category= "Transportation", PaymentMode="Cash", Description="Public and other transportation", Amount=150 },
new ExpenseData() {Category= "Transportation", PaymentMode="Debit Card", Description="Public and other transportation", Amount=250 }
};
}
public class ItemFields
{
public string Id { get; set; }
}
public List<ItemFields> Items = new List<ItemFields>() {
new ItemFields(){ Id= "Cash" },
new ItemFields(){ Id= "Debit Card" },
new ItemFields(){ Id= "Credit Card" },
new ItemFields(){ Id= "Net Banking" }
};
public void OnChange(Syncfusion.Blazor.DropDowns.ChangeEventArgs<string, ItemFields> args, RuleModel Rule)
{
Rule.Value = args.Value;
}
List<RuleModel> Rules = new List<RuleModel>()
{
new RuleModel { Label="PaymentMode", Field="PaymentMode", Type="String", Operator="equal", Value="Debit Card" },
new RuleModel { Label="Category", Field="Category", Type="String", Operator="equal", Value="Food" }
};
}
Hi Darren,
We have validated your reported query and prepared the sample based on your requirement. We can achieve your requirement using the code snippet. Here we create new instance of template for each rule, so it does not affect when we use this value template multiple times.
|
<QueryBuilderTemplates> <ValueTemplate> @{ string value = (string)context.Value; if(value == "") { value = DefaultValue; } } <SfDropDownList TValue="string" TItem="ItemFields" DataSource="@Items" @bind-Value="@value"> <DropDownListFieldSettings Text="Id"></DropDownListFieldSettings> <DropDownListEvents TItem="ItemFields" TValue="string" ValueChange="e => OnChange(e, context)"></DropDownListEvents> </SfDropDownList> </ValueTemplate> </QueryBuilderTemplates> |
Could you please check the above code and get back to us, if you need any further assistance on this.
And we will consider this query and correct it in our online documentation site. This documentation will get refreshed in our upcoming release.
Regards,
YuvanShankar A
Thankyou, that fixes the problem.
Hi Darren,
We are happy to hear that your requirement has been fulfilled. Please get back to us if you need any further assistance on this.
Regards,
YuvanShankar A
Further to this: the resolution you provided did set the default field value in the UI. However, it does not seem to be set in the Rules. Steps to reproduce using using the attached code:
* Choose "PaymentMode" from the dropdown list of fields
* The querybuilder condition is updated to show "PaymentMode StartsWith Cash" (correctly using the default value)
* Click the "Get query as SQL" button
* Expected result: query is "PaymentMode LIKE ('%Cash')"
* Actual result: query is "PaymentMode like ('%')
@page "/qb"
@using Syncfusion.Blazor.QueryBuilder
@using Syncfusion.Blazor.DropDowns
<div class="col-lg-12 control-section">
<SfQueryBuilder TValue="ExpenseData" Width="100%" DataSource="@DataSource" @ref="QueryBuilderRef">
<QueryBuilderEvents TValue="ExpenseData" Created="QueryBuilderCreated"></QueryBuilderEvents>
@* <QueryBuilderRule Condition="and" Rules="@Rules"></QueryBuilderRule> *@
<QueryBuilderColumns>
<QueryBuilderColumn Field="PaymentMode" Label="PaymentMode" Type=Syncfusion.Blazor.QueryBuilder.ColumnType.String>
<QueryBuilderTemplates>
<ValueTemplate>
@{
string value = (string)context.Value;
if (value == "")
{
value = DefaultValue;
}
}
<SfDropDownList TValue="string" TItem="ItemFields" DataSource="@Items" @bind-Value="@value">
<DropDownListFieldSettings Text="Id" Value="Id"></DropDownListFieldSettings>
<DropDownListEvents TItem="ItemFields" TValue="string" ValueChange="e => OnChange(e, context)"></DropDownListEvents>
</SfDropDownList>
</ValueTemplate>
</QueryBuilderTemplates>
</QueryBuilderColumn>
<QueryBuilderColumn Field="Category" Label="Category" Type=Syncfusion.Blazor.QueryBuilder.ColumnType.String></QueryBuilderColumn>
<QueryBuilderColumn Field="Description" Label="Description" Type=ColumnType.String></QueryBuilderColumn>
<QueryBuilderColumn Field="Amount" Label="Amount" Type=Syncfusion.Blazor.QueryBuilder.ColumnType.Number></QueryBuilderColumn>
</QueryBuilderColumns>
</SfQueryBuilder>
<button @onclick="GetQueryAsSql">Get query as sql</button>
<p>@QueryAsSql</p>
</div>
@code{
protected SfQueryBuilder<ExpenseData> QueryBuilderRef { get; set; }
public string DefaultValue = "Cash";
public List<ExpenseData> DataSource;
public class ExpenseData
{
public string Category { get; set; }
public string PaymentMode { get; set; }
public string Description { get; set; }
public int Amount { get; set; }
}
protected override void OnInitialized()
{
DataSource = new List<ExpenseData>()
{
new ExpenseData() {Category= "Food", PaymentMode="Credit Card", Description="Boiled peanuts", Amount=100 },
new ExpenseData() {Category= "Food", PaymentMode="Debit Card", Description="Boiled peanuts", Amount=200 },
new ExpenseData() {Category= "Food", PaymentMode="Cash", Description="Confederate cush", Amount=300 },
new ExpenseData() {Category= "Transportation", PaymentMode="Cash", Description="Public and other transportation", Amount=150 },
new ExpenseData() {Category= "Transportation", PaymentMode="Debit Card", Description="Public and other transportation", Amount=250 }
};
}
public class ItemFields
{
public string Id { get; set; }
}
public List<ItemFields> Items = new List<ItemFields>() {
new ItemFields(){ Id= "Cash" },
new ItemFields(){ Id= "Debit Card" },
new ItemFields(){ Id= "Credit Card" },
new ItemFields(){ Id= "Net Banking" }
};
public void OnChange(Syncfusion.Blazor.DropDowns.ChangeEventArgs<string, ItemFields> args, RuleModel Rule)
{
Rule.Value = args.Value;
}
// List<RuleModel> Rules = new List<RuleModel>()
// {
// new RuleModel { Label="PaymentMode", Field="PaymentMode", Type="String", Operator="equal", Value="Debit Card" },
// new RuleModel { Label="Category", Field="Category", Type="String", Operator="equal", Value="Food" },
// new RuleModel { Label="Amount", Field="Amount", Type="Number", Operator="notequal" }
// };
protected Task QueryBuilderCreated()
{
// QueryBuilderRef.SetRulesFromSql("PaymentMode = 'Debit Card'");
// Get the rules & display in the UI as SQL
// var rules = QueryBuilderRef.GetRules();
// QueryAsSql = QueryBuilderRef.GetSqlFromRules(rules);
return Task.CompletedTask;
}
public string QueryAsSql { get; set; }
protected void GetQueryAsSql()
{
var rules = QueryBuilderRef.GetRules();
if (rules is null)
{
QueryAsSql = "(null rules)";
}
else
{
QueryAsSql = QueryBuilderRef.GetSqlFromRules(rules);
}
}
}
Hi Darren,
We have validated your reported query and prepared the sample based on your requirement. We can achieve your requirement using the code snippet.
|
<QueryBuilderTemplates> <ValueTemplate> @{ string value = (string)context.Value; if (value == "") { value = DefaultValue; context.Value = DefaultValue; } } <SfDropDownList TValue="string" TItem="ItemFields" DataSource="@Items" @bind-Value="@value"> <DropDownListFieldSettings Text="Id" Value="Id"></DropDownListFieldSettings> <DropDownListEvents TItem="ItemFields" TValue="string" ValueChange="e => OnChange(e, context)"></DropDownListEvents> </SfDropDownList> </ValueTemplate> </QueryBuilderTemplates> |
Could you please check the above code and get back to us, if you need any further assistance on this.
Regards,
YuvanShankar A
Yes, that works - thankyou!
You are welcome, Darren. Please get back to us if you need any further assistance on this.
When using SfDropDownList as a valueTemplate in the Query Builder, the selected value does not populate when an existing rule is loaded or updated. Even though the rule contains a valid value, the DropDownList appears empty until the user manually selects an item again.
Expected behavior: the DropDownList should automatically display the value associated with the rule when the Query Builder initializes or when rules are updated programmatically.
ValueTemplate in the Query Builder, and the selected value correctly populates when existing rules are loaded without requiring manual interaction.ValueTemplate feature allows you to define custom widgets for column values. To ensure the DropDownList reflects the rule’s value, you need to bind the Value property to context.Value during template rendering. Here’s an example implementation: <SfQueryBuilder TValue="ExpenseData" Width="100%" DataSource="@DataSource"> <QueryBuilderRule Condition="and" Rules="@Rules"></QueryBuilderRule> <QueryBuilderColumns> <QueryBuilderColumn Field="PaymentMode" Label="PaymentMode" Type=Syncfusion.Blazor.QueryBuilder.ColumnType.String> <QueryBuilderTemplates> <ValueTemplate> @{ string value = context.Value != null ? context.Value : DefaultValue; } <SfDropDownList TValue="string" TItem="ItemFields" DataSource="@Items" @bind-Value="@value"> <DropDownListFieldSettings Text="Id"></DropDownListFieldSettings> <DropDownListEvents TItem="ItemFields" TValue="string" ValueChange="e => OnChange(e, context)"></DropDownListEvents> </SfDropDownList> </ValueTemplate> </QueryBuilderTemplates> </QueryBuilderColumn> </SfQueryBuilder> |
Documentation reference : https://blazor.syncfusion.com/documentation/query-builder/templates#value-template