Templated control in ektron - ektron

I have tried to retrieve the taxonomy list using taxonomy tree, in edit i am selecting the taxonomy and getting TaxonomyID,by using the taxonomyID i want to display the data using taxonomy filters using templated control.I am unable to retrive the data.I am attaching HTML and Code what i have done,So please help me out for the solution.
<asp:View ID="View" runat="server">
<asp:Label ID="lblID" runat="server"></asp:Label>
<CMS:Directory CssClass="taxList" ID="TaxonomySummary1" EnableAjax="true" runat="server"
EnablePaging="false" />
<ektron:ContentModelSource ID="cntModelSourcs" runat="server" OrderByField="DateCreated"
OrderByDirection="Descending">
<TaxonomyFilters>
<ektron:ContentTaxonomyFilter Operator="Contains" ID="taxFilter" runat="server" />
</TaxonomyFilters>
<ContentFilters>
<ektron:ContentFilter Field="Id" Operator="EqualTo" Value="" />
</ContentFilters>
</ektron:ContentModelSource>
<ektron:ContentView ID="ContentView1" runat="server" ModelSourceID="cntModelSourcs"
EktronCustomTemplate="Ektron_ContentList_Template" >
</ektron:ContentView>
</asp:View>
enter code here
_edit" class="TSWidget">
<div class="ByTaxonomy TSTabPanel">
<div style="height: 150px; overflow: auto;">
<UC:TaxonomyTree ID="TaxonomyTree1" runat="server" />
</div>
<hr />
</div>
<div class="ByProperty TSTabPanel">
<table style="width: auto;">
<tr>
<td class="label">
<%=m_refMsg.GetMessage("lbl taxonomy id:")%>
</td>
<td>
<asp:TextBox ID="taxonomyid" CssClass="folderid" runat="server" Style="width: auto;"></asp:TextBox>
</td>
</tr>
<tr>
<td class="label">
<%=m_refMsg.GetMessage("lbl taxonomy path:")%>
</td>
<td>
<asp:Label ID="taxonomypath" CssClass="taxonomypath" runat="server"></asp:Label>
</td>
</tr>
</table>
</div>
<div class="TSEditControls">
<asp:Button ID="CancelButton" CssClass="TSCancel" runat="server" Text="Cancel" OnClick="CancelButton_Click" />
<asp:Button ID="SaveButton" CssClass="TSSave" runat="server" OnClick="SaveButton_Click" Text="Save" />
</div>
</div>
</asp:View>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ektron.Cms;
using Ektron.Cms.Widget;
using Ektron.Cms.Common;
using Ektron.Cms.API;
using Ektron.Cms.Organization;
using Ektron.Cms.Framework.Organization;
using System.Text;
using Ektron.Cms.Search.Expressions;
using Ektron.Cms.Search;
using Ektron.Cms.Framework;
public partial class widgets_Content_TaxonomyFilter : System.Web.UI.UserControl,IWidget
{
# region Properties
protected string appPath = "";
private Ektron.Cms.CommonApi _commonAPI = new CommonApi();
private long _taxonomyid;
public string TaxonomySelected = "selected";
public string PropertySelected = "selected";
public string m_strTaxonomyPath = "/";
private string _taxonomypath;
[WidgetDataMember(0)]
public long TaxonomyId { get { return _taxonomyid; } set { _taxonomyid = value; } }
[WidgetDataMember("")]
public string TaxonomyPaths { get { return _taxonomypath; } set {
_taxonomypath = value; } } private IWidgetHost _host;
protected ContentAPI m_refContentApi = new ContentAPI();
protected EkMessageHelper m_refMsg;
#endregion
# region Page Load
protected void Page_Load(object sender, EventArgs e)
{
taxFilter.Value = TaxonomyId.ToString();
ContentView1.DataBind();
}
#endregion
#region Page Init
protected void Page_Init(object sender, EventArgs e)
{
m_refMsg = m_refContentApi.EkMsgRef;
CancelButton.Text = m_refMsg.GetMessage("btn cancel");
SaveButton.Text = m_refMsg.GetMessage("btn save");
_host = Ektron.Cms.Widget.WidgetHost.GetHost(this);
_host.Title = "Templated Control";
_host.Edit += new EditDelegate(EditEvent);
_host.Maximize += new MaximizeDelegate(delegate() { Visible = true; });
_host.Minimize += new MinimizeDelegate(delegate() { Visible = false; });
_host.Create += new CreateDelegate(delegate() { EditEvent(""); });
_host.ExpandOptions = Expandable.ExpandOnEdit;
appPath = _commonAPI.AppPath;
Load += new EventHandler(delegate(object PreRenderSender, EventArgs Evt) { if
(ViewSet.GetActiveView() != Edit) SetTaxonomySummary(); });
ViewSet.SetActiveView(View);
}
protected void SetTaxonomySummary()
{
if (TaxonomyId > 0)
{
lblID.Text = Convert.ToString(taxFilter.Value);
}
}
#endregion
#region EditEvent
void EditEvent(string settings)
{
try
{
string sitepath = _commonAPI.SitePath;
string webserviceURL = sitepath + "widgets/taxonomysummary/TSHandler.ashx";
JS.RegisterJSInclude(this, JS.ManagedScript.EktronJS);
Ektron.Cms.API.JS.RegisterJSInclude(this,
Ektron.Cms.API.JS.ManagedScript.EktronJQueryClueTipJS);
JS.RegisterJSInclude(this, JS.ManagedScript.EktronScrollToJS);
JS.RegisterJSInclude(this, sitepath + "widgets/taxonomysummary/behavior.js",
"TaxonomySummaryWidgetBehaviorJS");
if (TaxonomyId > 0)
{
TaxonomySelected = "";
JS.RegisterJSBlock(this, "Ektron.PFWidgets.TaxonomySummary.webserviceURL =
\"" + webserviceURL + "\";
Ektron.PFWidgets.TaxonomySummary.setupAll();
Ektron.PFWidgets.TaxonomySummary.SetTabs.init()
; ", "EktronPFWidgetsTSInit");
}
else
{
PropertySelected = "";
JS.RegisterJSBlock(this, "Ektron.PFWidgets.TaxonomySummary.webserviceURL =
\"" + webserviceURL + "\";
Ektron.PFWidgets.TaxonomySummary.setupAll(); ", "EktronPFWidgetsTSInit");
}
Css.RegisterCss(this, sitepath + "widgets/taxonomysummary/TSStyle.css",
"TSWidgetCSS");
ViewSet.SetActiveView(Edit);
//set taxonomy path
Ektron.Cms.API.Content.Taxonomy _apiTaxonomy = new
Ektron.Cms.API.Content.Taxonomy();
Ektron.Cms.TaxonomyRequest taxRequest = new Ektron.Cms.TaxonomyRequest();
taxRequest.TaxonomyId = TaxonomyId;
taxRequest.IncludeItems = false;
taxRequest.TaxonomyLanguage = _apiTaxonomy.ContentLanguage;
Ektron.Cms.TaxonomyData taxData = _apiTaxonomy.LoadTaxonomy(ref taxRequest);
if (!(taxData == null || string.IsNullOrEmpty(taxData.Path)))
{
taxonomypath.Text = taxData.Path;
m_strTaxonomyPath = taxData.Path;
}
else
{
m_strTaxonomyPath = "";
}
}
catch (Exception e)
{
ViewSet.SetActiveView(View);
}
}
#endregion
#region Button Events
protected void CancelButton_Click(object sender, EventArgs e)
{
ViewSet.SetActiveView(View);
}
protected void SaveButton_Click(object sender, EventArgs e)
{
int taxID = Convert.ToInt32(taxonomyid.Text);
TaxonomyId = taxID;
taxFilter.Value = TaxonomyId.ToString();
SetTaxonomySummary();
_host.SaveWidgetDataMembers();
ViewSet.SetActiveView(View);
}
#endregion
public EventArgs e { get; set; }
}

If I understand your question correctly, you have the taxonomy id and want to display all the content within that taxonomy. If that is not what you are after, then please clarify your question, and I'll try to help as best I can.
I find that the added baggage that comes along with a widget can sometimes make it hard to test for correct API and server control usage. For that reason, I'd recommend starting off with a simple ASPX page.
<ektron:ContentModelSource ID="contentModelSource" runat="server">
</ektron:ContentModelSource>
<ektron:ContentView ID="ContentView1" runat="server" ModelSourceID="contentModelSource" EktronCustomTemplate="Ektron_ContentList_Template">
</ektron:ContentView>
Normally, the examples you'll find for the templated server controls show the declarative syntax for setting the filters, where you put them right into the ASPX markup - right inside the ContentModelSource control. Something like:
<TaxonomyFilters>
<ektron:ContentTaxonomyFilter Field="Id" Operator="EqualTo" Value="208" />
</TaxonomyFilters>
(More examples here and here.)
But for what it sounds like you want to accomplish, you need to define the filters via code. This code does just that:
protected long TaxonomyId
{
get
{
long id;
long.TryParse(Request.QueryString["id"], out id);
return id;
}
}
protected bool IsRecursive
{
get
{
bool recursive;
bool.TryParse(Request.QueryString["recursive"], out recursive);
return recursive;
}
}
protected void Page_Init(object sender, EventArgs e)
{
if (TaxonomyId > 0)
{
if (IsRecursive)
{
var tm = new TaxonomyManager();
var td = tm.GetItem(TaxonomyId);
if (td != null)
{
var pathFilter = new ContentTaxonomyFilter();
pathFilter.Field = ContentTaxonomyProperty.Path;
pathFilter.Operator = CriteriaFilterOperator.StartsWith;
pathFilter.Value = td.Path;
contentModelSource.TaxonomyFilters.Add(pathFilter);
}
}
else
{
var filter = new ContentTaxonomyFilter();
filter.Field = ContentTaxonomyProperty.Id;
filter.Value = TaxonomyId.ToString();
filter.Operator = CriteriaFilterOperator.EqualTo;
contentModelSource.TaxonomyFilters.Add(filter);
}
}
}
A couple of things to note:
The TaxonomyId is a property. I did this so that there would be an easy point of comparison between this simple ASPX page and a custom widget where your property would be decorated with the WidgetDataMember attribute.
The code is in the Page_Init event handler. That is important. Page_Load is too late in the page's lifecycle. I assume this would also be true in the context of a widget.
My code for when IsRecursive == true is not necessarily optimized. You could get reasonable performance by turning on caching in the FrameworkAPI, but the idea of calling the api to get the taxonomyData and then using that to set the filter for the content seems a little off. Ideally, the ContentTaxonomyFilter would have a "Recursive" property.

Related

How to update a value on InputText [Blazor NetCore 5.0]

In my .razor page I have an InputText, what I want is to update that number as soon as it is being typed, specifically is to put a space every 4 characters, how am I trying to do it?
<InputText #bind-Value="oPagos.NumeroEnTarjeta" #onkeydown="#Tecleando" type="number"
onchange="()=>NumberChanged()" id="card-number" placeholder="1111 2222 3333 4444" class="input" maxlength="16" />
Then,
public void Tecleando(KeyboardEventArgs e)
{
//Console.WriteLine(e.Key);
oPagos.NumeroEnTarjeta = generateSpaces(oPagos.NumeroEnTarjeta);
Console.WriteLine(oPagos.NumeroEnTarjeta);
}
I have a function where I plan to take all the value from the bind, ie: oPayments.NumberOnCard, and every 4 spaces generate a space.
This does not work for me for two reasons.
the first number that I type is taken from the #Onkeydown event but the variable oPagos.NumeroEnTarjeta is empty.
I don't know how to update the value of the InputText, as I show in the following image I effectively modify the variable oPagos.NumeroEnTarjeta, but I can't get the user to see it rendered in the text box.
Should I take another way or how do I fix what I have? Thank you.
Update
I succeeded in doing something similar, but with two different events, onblur and onfocus.
I use onfocus to remove the spaces and I use onblur to add my spaces, however, what I would like to do is while I'm writing
I got some Problems with Dynamic Data using Bind-Value / Bind so i started using Blazorise and solve my problems, a possible solution is this one:
<Field>
<TextEdit Text="#opagos.NumeroEnTarjeta" TextChanged="#MethodThatBringSpaces"></TextEdit>
<Field>
Then in #code
Task MethodThatBringSpaces(string value){
opagos.NumeroEnTarjeta = generateSpaces(value);
}
Also you can use the data that you want (i use string in this case) and you can add the same things than blazor (id,placeholder,etc.)
Here's a set of code which I think does basically what you want. It was written to answer a similar question on here a few months ago! I've used dashes instead of spaces to show the space being filled. It's was coded in Net6.0 but should be Ok in Net5.0.
You will probably need to tweak it a little to fit your exact needs:
CreditCardCode.razor
#namespace StackOverflowAnswers.Components
#inherits InputBase<string>
<input #attributes="AdditionalAttributes"
class="#CssClass"
value="#stringValue"
#oninput="OnInput"
#onchange="this.OnValueChanged"
#onfocus="OnFocus"
#onblur="OnBlur"
/>
CreditCardCode.razor.cs
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using System.Text.RegularExpressions;
namespace StackOverflowAnswers.Components;
public partial class CreditCardCode : InputBase<string>
{
private string stringValue = String.Empty;
private string _currentValue = String.Empty;
// Sets up the initial value of the input
protected override void OnInitialized()
{
_currentValue = this.Value ?? string.Empty;
this.stringValue = this.GetCodeValue(_currentValue);
base.OnInitialized();
}
private async Task OnInput(ChangeEventArgs e)
{
var rawValue = e.Value?.ToString();
stringValue = "";
await Task.Yield();
_currentValue = this.GetCodeValue(rawValue ?? string.Empty);
this.stringValue = this.FormatValueAsString(_currentValue);
}
private async Task OnFocus(FocusEventArgs e)
{
stringValue = "";
await Task.Yield();
this.stringValue = this.FormatValueAsString(_currentValue);
}
private async Task OnBlur(FocusEventArgs e)
{
stringValue = "";
await Task.Yield();
this.stringValue = this.GetCodeValue(_currentValue);
}
// We set the base CurrentValueAsString to let it handle all the EditContext changes and validation process
private void OnValueChanged(ChangeEventArgs e)
=> this.CurrentValueAsString = e.Value?.ToString() ?? string.Empty;
// Necessary override for InputBase
protected override bool TryParseValueFromString(string? value, out string result, out string validationErrorMessage)
{
result = value ?? string.Empty;
if (!string.IsNullOrEmpty(value) && value.Length == 19)
{
validationErrorMessage = string.Empty;
return true;
}
else
{
validationErrorMessage = "Value must be nnnn-nnnn-nnnn-nnnn";
return false;
}
}
protected override string FormatValueAsString(string? value)
=> value ?? string.Empty;
private string GetCodeValue(string value)
{
value = new string(value.Where(c => char.IsDigit(c)).ToArray());
value = value.Length > 16
? value.Substring(0, 16)
: value;
var reg = new Regex(#"([0-9]{1,4})");
var matches = reg.Matches(value);
var outvalue = string.Empty;
if (matches.Count > 0)
{
foreach (Match match in matches)
{
outvalue = $"{outvalue}-{match.Value}";
}
outvalue = outvalue.Trim('-');
return outvalue;
}
return string.Empty;
}
}
Test Page
#page "/"
#using StackOverflowAnswers.Components
<h3>EditForm</h3>
<div class="container-fluid">
<EditForm EditContext=editContext>
<div class="row">
<div class="col-2">
Credit Card No:
</div>
<div class="col-4">
<CreditCardCode class="form-control" #bind-Value="this.model.CreditCardNo"/>
</div>
<div class="col-4">
<ValidationMessage For="() => this.model.CreditCardNo" />
</div>
</div>
</EditForm>
<div class="row">
<div class="col-2">
Credit Card No:
</div>
<div class="col-4">
#model.CreditCardNo
</div>
</div>
</div>
#code {
private EditContext? editContext;
private ModelData model = new ModelData();
protected override Task OnInitializedAsync()
{
this.editContext = new EditContext(model);
return Task.CompletedTask;
}
class ModelData
{
public string CreditCardNo { get; set; } = string.Empty;
}
}

Fire event when the textbox changes in Blazor

I'm using EditForm and InputText to achieve data binding and forms validation. (Using <input #bind="SomeProperty" /> doesn't seem to fire component validation.)
I want to attach an event handler that gets fired whenever the value of the textbox changes:
<InputText #bind-Value="#model.ZipCode" #onkeypress="#model.InvokeThisMethod)"></InputText>
This sort of works, but when I'm in the event handler it's apparently firing before ZipCode has updated. The goal here is to do a thing when the zip code reaches 5 characters, not when the text input loses focus. I've also tried just forcing the change event to fire oninput but that just creates an error on the console about ChangedEventArgs to string not working.
How can I fire an event after the input field has updated the data binding?
After trying everything under the sun to get the grid to reload via the search string after inserting a new record, and failing, I found that I can just reload the grid by setting the search string to empty and displaying all the results (simply having a value in the search box prevents the grid from refreshing after an insert - there is no solution I could get to work for this), but at least it shows the record as being inserted. While this isn't the answer I was looking for, it will suffice for now.
Here's the index.razor page (final):
#page "/"
#inject IConfiguration config
#inject DialogService dialog
#inject NotificationService notification
<PageTitle>Memo Master</PageTitle>
<RadzenButton Click="() => GetMemos()" Text="Get Memos" ButtonStyle="ButtonStyle.Primary" ButtonType="ButtonType.Submit" />
<RadzenTextBox #ref="searchBox" Name="SearchPhrase" #bind-Value="#SearchString" MaxLength="400" #oninput="#(args => SearchString = args.Value?.ToString())" #onkeydown="#Enter" />
<RadzenButton Click="() => OpenMemo(0)" Text="New Memo" Icon="add_circle_outline" ButtonStyle="ButtonStyle.Secondary" />
<br />
<br />
#if (FoundMemos != null && !busy)
{
<RadzenDataGrid #ref=this.grid Data="#FoundMemos" TItem="MemoSearch" AllowFiltering="true" AllowSorting="true" AllowColumnResize="true" AllowPaging="true" PageSize=20
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" SelectionMode="DataGridSelectionMode.Single" #bind-Value="#SelectedMemos" RowClick="#OnRowClicked">
<Columns>
<RadzenDataGridColumn TItem="MemoSearch" Title="Index" Width="70px" Filterable="false" TextAlign="TextAlign.Left">
<Template Context="m">
<RadzenText TextStyle="TextStyle.Caption">#m.Idx.ToString()</RadzenText>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="MemoSearch" Property="Title" Title="Title">
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="MemoSearch" Title="Modified" Width="140px" TextAlign="TextAlign.Right">
<Template Context="m">
<RadzenText TextStyle="TextStyle.Caption">#m.ModifiedOn.ToString("MM/dd/yyyy hh:mm tt")</RadzenText>
</Template>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
}
else
{
<DisplaySpinner />
}
<br />
<br />
<RadzenButton Click="Reset" Text="Reset" ButtonStyle="ButtonStyle.Secondary" />
#code {
[Parameter]
public string? SearchString { get; set; }
List<MemoSearch> FoundMemos = new();
private string DBConnStr { get; set; } = "";
public DB dB = new();
IList<MemoSearch>? SelectedMemos;
RadzenTextBox? searchBox;
private bool busy;
private RadzenDataGrid<MemoSearch>? grid; //reference to grid, so forced reloading can happen - though it doesn't actually work
async Task OpenMemo(int Idx)
{
string DialogTitle = (Idx == 0) ? "Create New Memo" : $"Edit Memo {Idx.xToStr()}";
object? RefreshResults = await dialog.OpenAsync<MemoDetails>(DialogTitle, new Dictionary<string, object>() { { "Idx", Idx } });
RefreshResults = (RefreshResults == null) ? false : RefreshResults;
if (RefreshResults.xToBoo())
{
if (Idx == 0) SearchString = ""; //force setting to empty reloads grid but only w/o search entry
await GetMemos();
}
await ReturnFocus();
}
protected override async Task OnInitializedAsync()
{
dB.DBConnStr = await Task<string>.Run(()=> config.GetConnectionString("DBConnStr"));
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender) await ReturnFocus(); //NOTE: this is for Radzen "elements"
}
public async Task GetMemos()
{
busy = true;
FoundMemos = await dB.MemoSearchByPageFilterSortAsync(SearchString, PageSize: 9999);
busy = false;
}
public async Task Reset()
{
FoundMemos = new();
SearchString = "";
await ReturnFocus();
}
public async void Enter(KeyboardEventArgs e)
{
if (e.Code == "Enter" || e.Code == "NumpadEnter" || e.Key == "Enter")
{
await GetMemos();
StateHasChanged(); //need to call this here after keypress, lest you get a continual spinner
}
}
async Task OnRowClicked(Radzen.DataGridRowMouseEventArgs<MemoSearch> args)
{
if (args != null)
{
await OpenMemo(args.Data.Idx);
}
}
async Task ReturnFocus()
{
if (searchBox != null) await searchBox.Element.FocusAsync();
}
}
and the MemoDetails.razor page:
#inject IConfiguration config
#inject DialogService dialog
#inject NotificationService notification
#if (memo != null)
{
<RadzenTemplateForm TItem="Memo" Data=#memo Submit=#OnSubmit>
<p>
<RadzenLabel Component="Title" Text="Title" />
<RadzenTextBox id="MemoTitle" Name="Title" #bind-Value=#memo.Title MaxLength="400" />
<RadzenRequiredValidator Component="Title" Text="Title is required!" />
</p>
<p>
<RadzenLabel Component="Body" Text="Memo" />
<RadzenTextArea id="MemoBody" Name="Body" #bind-Value=#memo.Body Rows="18" />
</p>
<p>
<RadzenLabel Component="Keywords" Text="Key Words" />
<RadzenTextBox id="MemoKeywords" Name="Keywords" #bind-Value=#memo.Keywords MaxLength="400" />
</p>
<RadzenButton ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Success" Icon="save" Text="Save" BusyText="Saving ..." IsBusy=#busy />
#if (Idx > 0)
{
<RadzenButton ButtonType="ButtonType.Button" ButtonStyle="ButtonStyle.Danger" Icon="delete" Text="Delete" Click="#((args) => DeleteMemo(memo.Idx))" #onclick:stopPropagation="true"></RadzenButton>
}
<RadzenButton Text="Close" Click="() => dialog.Close(false)" ButtonStyle="ButtonStyle.Light" />
</RadzenTemplateForm>
}
#code {
[Parameter]
public int Idx { get; set; } = 0;
public DB dB = new();
Memo? memo;
bool busy;
protected override async void OnInitialized()
{
dB.DBConnStr = config.GetConnectionString("DBConnStr");
memo = (Idx == 0) ? new Memo() : await GetMemoByIdx(Idx);
await InvokeAsync(() => StateHasChanged()).ConfigureAwait(false); //IMPORTANT!!
}
public async Task<Memo> GetMemoByIdx(int Idx) => await dB.MemoSelectByIdxAsync(Idx);
async Task OnSubmit(Memo memo)
{
int Result;
bool RefreshResults = false;
if (memo.ModifiedOn == DateTime.MinValue) memo.ModifiedOn = DateTime.Now;
string NotificationDetailMessage = memo.Idx == 0 ? "New Memo has been created." : $"Memo {memo.Idx} has been saved.";
busy = true;
Result = await dB.MemoUpsertAsync(memo);
if (Result < -1)
{
notification.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "Error Saving", Detail = "An error saving this record has occured!\n" + dB.LastErrorMsg, Duration = 4000 });
}
else
{
notification.Notify(new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "Save Success", Detail = NotificationDetailMessage, Duration = 2000 });
RefreshResults = true;
}
busy = false;
dialog.Close(RefreshResults);
}
async Task DeleteMemo(int Idx)
{
int Result;
bool RefreshResults = false;
var confirmResult = await dialog.Confirm("Are you sure?", "Confirm Memo Deletion");
if (confirmResult.HasValue && confirmResult.Value)
{
busy = true;
Result = await dB.MemoDeleteByIdxAsync(Idx);
if (Result < -1)
{
notification.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "Error Deleting", Detail = "An error deleting this record has occured!\n" + dB.LastErrorMsg, Duration = 4000 });
}
else
{
notification.Notify(new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "Deletion Success", Detail = $"Memo {Idx} has been deleted.", Duration = 2000 });
RefreshResults = true;
}
}
busy = false;
dialog.Close(RefreshResults);
}
}
Good enough, for now, but still baffled as to what Radzen is doing behind the scenes.
<InputText class="form-control" Value="#model.ZipCode" ValueExpression="#( ()=> model.ZipCode )" ValueChanged="#( (string s) => model.InvokeThisMethod(s) )"></InputText>
I didn't find this in the Microsoft documentation. I found it on the Telerik site for their Blazor controls (which apparently works for the non Telerik controls).
Dealing with form fields in Blazor really sucks right now.
<input #bind="model.Property" />
or
<InputText #bind-Value="model.Property" />
and then the ValueExpression attributes shown above. The intellisense in .razor files for VS2019 is poorly implemented. This sucks.

Wicket dynamicly add data from database to page

I'm trying to add some data into page from database, after applying "filter"
After submit form, candidate list is update and I want to push this changes into page.
How can I do this in wicket ?
.java file
public class SearchCandidate extends WebPage {
private SearchCandidateModel searchCandidateModel = new SearchCandidateModel();
private List<CandidateEntity> candidate = new ArrayList();
public SearchCandidate(PageParameters p) {
super(p);
final TextField<String> firstName = new TextField<>("first_name", new PropertyModel<String>(searchCandidateModel, "firstName")); //Filter
final DataView dataView = new DataView("simple", new ListDataProvider(candidate)) {
public void populateItem(final Item item) {
final CandidateEntity user = (CandidateEntity) item.getModelObject();
item.add(new Label("firstName", user.getFirstName()));
}
};
Form<?> form = new Form<Void>("step1") {
#Override
protected void onSubmit() {
candidate = databse.findCandidate(searchCandidateModel.getFirstName());
//UPDATE TABLE
}
};
form.add(firstName);
add(form);
add(dataView);
}
}
html file:
<form wicket:id="step1">
<input wicket:id="first_name" type="text" size="30"/>
</form>
<table cellspacing="0" class="dataview">
<tbody>
<tr wicket:id="simple">
<td><span wicket:id="name">Test ID</span></td>
</tr>
</tbody>
</table>
You can make you DataProvider - dynamic:
new ListDataProvider() {
#Override protected List getData() {
if (noFilter) return emptyList
else return database.getList(filter)
}
}
This way the provider will always load the data according to your data filter.
For more information about static vs. dynamic models/providers check:
https://cwiki.apache.org/confluence/display/WICKET/Working+with+Wicket+models#WorkingwithWicketmodels-DynamicModels

Adding LinqDataSource Where Parameters in Code-Behind

Reading simple table using LinqDataSource. Table name is ZipCode with three columns: ZipCode, City, State). Read works fine with no filter, but when I add "Where" parameters to LinqDataSource, it fails in the GridView databind with an error, "No property or field "CityValue" exists in the type "ZipCode".
ASPX:
<asp:GridView ID="grdLDS" runat="server" AllowPaging="True" AllowSorting="True"
DataSourceID="ldsData" AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="ZIPCODE1" HeaderText="ZipCode" SortExpression="ZIPCODE1" />
<asp:BoundField DataField="CITY" HeaderText="City" SortExpression="CITY" />
<asp:BoundField DataField="STATE" HeaderText="State" SortExpression="STATE" />
</Columns>
</asp:GridView>
<asp:LinqDataSource ID="ldsData" runat="server" ContextTypeName="LinqLayer.CommonDataDataContext"
TableName="ZipCodes" OnSelecting="ldsData_Selecting" OnSelected="ldsData_Selected" >
</asp:LinqDataSource>
Code-Behind:
protected void ldsData_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
if (!cbxLDS.Checked)
{
e.Cancel = true;
return;
}
ldsData.WhereParameters.Clear();
StringBuilder where = new StringBuilder();
if (!string.IsNullOrEmpty(txtFilterByZip.Text))
{
where.Append("ZIPCODE1.StartsWith(#ZipValue)");
ldsData.WhereParameters.Add("#ZipValue", txtFilterByZip.Text);
}
if (!string.IsNullOrEmpty(txtFilterByCity.Text))
{
if (where.Length > 0) where.Append(" & ");
where.Append("CITY.StartsWith(#CityValue)");
ldsData.WhereParameters.Add("#CityValue", txtFilterByCity.Text);
}
if (!string.IsNullOrEmpty(txtFilterByState.Text))
{
if (where.Length > 0) where.Append(" & ");
where.Append("STATE.StartsWith(#StateValue)");
ldsData.WhereParameters.Add("#StateValue", txtFilterByState.Text);
}
ldsData.Where = where.ToString();
}
protected void ldsData_Selected(object sender, LinqDataSourceStatusEventArgs e)
{
LDSRowCount = e.TotalRowCount;
}
private int RefreshLDSData()
{
grdLDS.DataBind(); // <== CODE FAILS ON THIS LINE
return LDSRowCount;
}
private IEnumerable<ZipCode> FilterLDSData(IEnumerable<ZipCode> rows)
{
return rows;
}
you can try like this in where parameter with linqdatasource..
NOte :this is just example how to use the where parameter using linqdatasource...
public void LinqDataSource1_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
var db = new MyDataContext())
var subjectFilter = e.WhereParameters("Subject");
var reporters = from spName in db.spReporter()
where spName.Subject.Contains(subjectFilter)
select new Reporter(spName.Id, spName.InqDate, spName.Subject);
e.Result = reporters;
}
pls go through this link for more info
Thanks to Andy Robinson, here is the solution:
protected void ldsData_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
if (!cbxLDS.Checked)
{
e.Cancel = true;
return;
}
var dc = new CommonDataDataContext();
var query = dc.ZipCodes.Select(r => new ZipData()
{
ZipCode = r.ZIPCODE1,
City = r.CITY,
State = r.STATE,
});
e.Result = ldsFilter(query);
}
private IQueryable<ZipData> ldsFilter(IQueryable<ZipData> rows)
{
if (!string.IsNullOrEmpty(txtFilterByZip.Text))
{
rows = rows.Where(r => r.ZipCode.StartsWith(txtFilterByZip.Text));
}
if (!string.IsNullOrEmpty(txtFilterByCity.Text))
{
rows = rows.Where(r => r.City.StartsWith(txtFilterByCity.Text));
}
if (!string.IsNullOrEmpty(txtFilterByState.Text))
{
rows = rows.Where(r => r.State.StartsWith(txtFilterByState.Text));
}
return rows;
}
lds_Data_Selecting event provides the structure of the query, and the ldsFilter method does the dynamic filtering. This method must accept and return an iQueryable.

Custom control child controls not persisted to ViewState in ASP.NET 4.0

We just switched target framework in our ASP.NET web application from 3.5 to 4.0. We ran into the following problem:
We have a couple of custom controls that worked fine in 3.5 but now with 4.0 they are not persisted in ViewState, one of them is basically a wrapper for other controls that inherits the Label class and the aspx-code looks like this:
<fsc:FormLabel ID="l_purchaserNo" runat="server" CssClass="label" Text="Purchaser">
<asp:TextBox ID="tb_purchaserNo" runat="server" CssClass="textBox" MaxLength="50" />
</fsc:FormLabel>
and the resulting html is:
<span id="l_purchaserNo" class="label">
<label class="header" for="tb_purchaserNo">Purchaser</label>
<span class="valueContainer">
<input name="tb_purchaserNo" type="text" id="tb_purchaserNo" class="textBox" />
</span>
</span>
So the control basically just adds a few span-tags and a label that is connected to the textbox.
After postback the html-code in 4.0 was:
<span id="l_purchaserNo" class="label"></span>
i.e. everything within the outer wrapper was gone and anything entered in the textbox could not be retreived from code behind.
Below you find the code for our FormLabel class.
We found that by setting ViewStateMode=Disabled on our custom control fsc:FormLabel and ViewStateMode=Enabled on the asp:TextBox the inner controls where persisted to ViewState but at the same time we lost ViewState on the wrapper and since we translate the text on the wrapper label we need viewstate for this as well (actually we tried every combination and setting ViewStateMode=Enabled on fsc:FormLabel did not help, regardless of how we set the ViewStateMode on the page). EnableViewState is true on all levels.
Could someone tell us how to get ViewState to work as before in 3.5, on ALL controls - wrapper as well as wrapped controls?
Thanks
Christian, Zeljko, Jonas
using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace FormLabel
{
public class FormLabel : Label
{
private bool HasChildren
{
get
{
return Controls.Count > 0;
}
}
public override string Text
{
get
{
if (!HasChildren)
{
return base.Text;
}
var text = ViewState[ID + "Text"] as String;
if (text != null)
{
((LiteralControl)Controls[0]).Text = text;
}
return ((LiteralControl)Controls[0]).Text;
}
set
{
if (!HasChildren)
{
base.Text = value;
return;
}
((LiteralControl)Controls[0]).Text = value;
}
}
public void SetText(string text)
{
((LiteralControl)Controls[0]).Text = text;
ViewState[ID + "Text"] = text;
}
public bool IndicateRequired
{
get
{
object state = ViewState[String.Format("{0}_IR", ID)];
return state != null && (bool)state;
}
set
{
ViewState[String.Format("{0}_IR", ID)] = value;
}
}
protected override void OnLoad(EventArgs e)
{
ViewState[ID + "Text"] = Text;
base.OnLoad(e);
}
protected override void Render(HtmlTextWriter writer)
{
if (HasChildren)
{
List<Control> controls = Controls.GetControls();
List<BaseValidator> validators = Controls.GetValidators();
WriteLabelControl(writer);
WriteRequiredIndicator(writer);
WriteControlHeader(writer, validators, this.GetFirstControl());
WriteInnerControls(writer, controls);
WriteLabelEndControl(writer);
return;
}
base.Render(writer);
}
private void WriteLabelControl(HtmlTextWriter writer)
{
writer.WriteBeginTag("span");
writer.WriteAttribute("id", ClientID);
writer.WriteAttribute("class", CssClass);
foreach (string attributeKey in Attributes.Keys)
{
writer.WriteAttribute(attributeKey, Attributes[attributeKey]);
}
writer.Write(HtmlTextWriter.TagRightChar);
}
private void WriteRequiredIndicator(HtmlTextWriter writer)
{
if (IndicateRequired)
{
writer.WriteBeginTag("span");
writer.WriteAttribute("class", "requiredIndicator");
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteEndTag("span");
}
}
private void WriteControlHeader(HtmlTextWriter writer, IEnumerable<BaseValidator> validators, Control userControl)
{
writer.WriteBeginTag("label");
writer.WriteAttribute("class", "header");
if (userControl != null)
{
writer.WriteAttribute("for", userControl.ClientID);
}
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(Text);
foreach (BaseValidator validator in validators)
{
validator.CssClass = "Error";
validator.RenderControl(writer);
}
writer.WriteEndTag("label");
}
private static void WriteInnerControls(HtmlTextWriter writer, IList<Control> controls)
{
writer.WriteBeginTag("span");
writer.WriteAttribute("class", "valueContainer");
writer.Write(HtmlTextWriter.TagRightChar);
for (int i = 1; i < controls.Count; i++)
{
controls[i].RenderControl(writer);
}
writer.WriteEndTag("span");
}
private static void WriteLabelEndControl(HtmlTextWriter writer)
{
writer.WriteEndTag("span");
}
}
#region Nested type: Extensions
public static class Extensions
{
public static List<BaseValidator> GetValidators(this ControlCollection controls)
{
var validators = new List<BaseValidator>();
foreach (Control c in controls)
{
if (c is BaseValidator)
{
validators.Add(c as BaseValidator);
}
}
return validators;
}
public static List<Control> GetControls(this ControlCollection controls)
{
var listcontrols = new List<Control>();
foreach (Control c in controls)
{
if (!(c is BaseValidator))
{
listcontrols.Add(c as Control);
}
}
return listcontrols;
}
public static Control GetFirstControl(this Control container)
{
return (new InputControlFinder().FindFirstInputControl(container));
}
private class InputControlFinder
{
public Control FindFirstInputControl(Control control)
{
Control input = null;
foreach (Control child in control.Controls)
{
if (child is TextBox || child is DropDownList || child is CheckBox)
{
input = child;
}
else
{
input = FindFirstInputControl(child);
}
if (input != null)
{
return input;
}
}
return input;
}
}
}
#endregion
}