Persisting data on view state and relaying to Knockout.JS - c#

I'm currently working on an asp.net web form that uses Knockout, Bootstrap, and JQuery. I'm having an issue with data persistence through "Wizard steps."
What I would like to do is take in the mailing state of the client and persist it through to other pages, from there use Knockout to make fields visible and also create validation.
I've read that you can use hidden states to accomplish this but I've had issues getting the value to pass to Knockout and ultimately getting the other fields to show.
Here is the c# that does all the steps page to page.
protected void StepChanged(object sender, EventArgs e)
{
if (IsPostBack)
{
if (QuoteWizard.ActiveStepIndex == 0)
txtFirstName.Focus();
if (QuoteWizard.ActiveStepIndex == 1)
{
Session["State"] = ddlState.Value;
rblMailAddr.Focus();
}
if (QuoteWizard.ActiveStepIndex == 3)
{
txtDriverFName1.Value = txtFirstName.Value;
txtDriverMI1.Value = txtMI.Value;
txtDriverLName1.Value = txtLastName.Value;
String DOB;
DOB = Convert.ToDateTime(txtDOB.Value).ToString();
txtDriverDOB1.Value = DOB;
txtDriverFName1.Focus();
}
I find it odd that the txtDriverFName1.Value = txtFirstNAme.Value; passes properly but I can't get the state from a drop down list or the date of birth to pass from one step to the other.
<select id="ddlState" runat="server" class="form-control" data-bind="value: MailState, updateValue: 'afterkeydown'">
Followed by the list of states, then I try to pass it to knockout to make fields visible:
self.MailState = ko.observable("", { persist: "MailState" });
However, once I reach the next step the values in the ViewState are dropped and
<div class="btn-group" data-toggle="buttons" style="padding-left: 10px" data-bind="visible: MailState() == 'CA'">
no longer becomes visible even when CA is selected in the previous viewstate.
So how would I persist the value of my drop down list through 2 or more steps in the QuoteWizard.ActiveStepIndex and have that assigned to "MailState()" subsequently activating Knockout?

in data-bind the bindinghandler handle to excute expression, then visible bindinghandler will unwrap it to value from observable. But in your code you use
data-bind="visible: MailState == 'CA'" //MailState is observalbe then like function() == 'CA' - that not right
should change to:
data-bind="visible: MailState() == 'CA'"

Related

Display data (fetched from DB) into InputTextarea Blazor

I am trying to display some data fetched from database into a Textarea of my Razor page.
I have tried out something like this. Is this the correct way of displaying the data for view only?
Razor page code snippet:
#if(summaryProjection != null)
{
<div> Seller Data</div>
<textarea>
#summaryProjection.tradeSummary.articleCurrency
</textarea>
}
cs side code:
public Models.SummaryProjection summaryProjection = new Models.SummaryProjection();
protected override async Task OnInitializedAsync()
{
string Id = TID;
summaryProjection = await Http.GetFromJsonAsync<Models.SummaryProjection>($"api/T/summary?Id=" + Id);
}
If it's a block of text you want to display then textarea is as good a solution as any other (with some css formatting to make it pretty). You will need to add disabled to prevent editing. In your example you appear to want to display a currency value. for that it's not the best - just use a suitably styled input, again with disabled set.
<textarea disabled>
#summaryProjection.tradeSummary.articleCurrency
</textarea>

Boolean checkbox value

My question is about checkbox boolean value.
See the image below (image is of a View where user chooses the "seminar") and my current implementation.
//in the model, "Popunjen" is checkbox value which displays if a cert
//"seminar" is full or not. Value is set mannually on the "admin" page
public bool Popunjen { get; set; }
I need a functionality where, if user clicks "Upiši se" (Enroll in eng.) on "Seminar" where "Popunjen" or "Full" is true (for ex. last seminar in list), some sort of error messagge is displayed.
Is this best done on the View code of this page? And what would be the code behind it?
Without seeing the code of your MVC, I suppose you're building the View from a Controller [HttpGet] and the table rows are populated from DB query. You could check the value of the "Popunjen" and if it's true disable the "Upiši se", something like:
<td>
#if (item.Popunjen == true)
{
// disable "Upiši se"
// don't show it
}
else
{
// enable "Upiši se"
}
</td>

Get all items from html select list using ASP.net C#

I have the following select list:
<select name="Context" id="Context" size="5">
<option>Context1</option>
<option>Context2</option>
<option>Context3</option>
<option>Context4</option>
<option>Context5</option>
</select>
I am using javascript to move the items of this select list up and down (this is working). I would like to feed the resulting order back to ASP.net using C#.
If I use the following line of code I get only the selected item, how do I get the whole list?
string items = Request.Form["Context"];
You can get all items like this.
var ddlArray= new Array();
var ddl = document.getElementById('Context');
for (i = 0; i < ddl.options.length; i++) {
ddlArray[i] = ddl .options[i].value;
}
Now pass this JavaScript array to your code behind.
One answer is to modify the select to make it a ListBox and then access it programattically on the server:
<asp:ListBox runat="server" name="lstContext" id="lstContext" size="5">
<asp:ListItem>Context1</asp:ListItem>
<asp:ListItem>Context2</asp:ListItem>
<asp:ListItem>Context3</asp:ListItem>
<asp:ListItem>Context4</asp:ListItem>
<asp:ListItem>Context5</asp:ListItem>
</asp:ListBox>
Note that I renamed it lstContext as calling it Context will cause build failures (due to sharing a name with the existing Context object).
Then in your code, to access the values in the order they appear:
for (int i = 0; i < lstContext.Items.Count; i++)
{
string item = lstContext.Items[i].Value;
// Do something with it
}
Your javascript should still work on the ListBox as it does for the select, so this should remain unaffected.
create a hidden field (runat=server) and store the shuffled <options> into the hidden field; You can access content of hidden field at server side by string itemsOrderedChanged = Request.Form[<HiddenFieldId>];
try to pass JavaScript value to hidden field like this .
var hidden=document.getElementById('hidValue');
var string strValues="";
for(var i=0i<ddlArray.Length;i++){
strValues+=ddlArray[i]+",";
}
hidden.value=strValues;
And in page_load or what_ever event get this string and split it.
protected HtmlControls.HtmlInputHidden hidValue;
protected void Page_Load(object sender, System.EventArgs e)
{
dynamic hiddenValue = hidValue.Value;
string [] arr=hiddenValue.Split(",");
}

ASP/C# TextBox Validation

I need to create a webform where users can add, update, delete, retrieve customer data from a table in an SQL database.
Should have textboxes for each field in the table so that the users can enter details of the fields to update the table in the DB.
What im having trouble with is in the code behind the form i need to make a clear method to clear all the textboxes and the message label.
I also need to set validation requirements for each textbox. But i am unsure how to do this properly.
The textboxes are;
CustID, Firstname, Surname, Gender, Age, Address1, Address2, City, Phone, Mobile, Email, Confirm Email.
Now my main question is, how do i validate the textboxes? For example;
CustID is required. & Must be unique. Must be an integer and must be between 1 & 1000.
You should use RequiredValidator for example
http://www.w3schools.com/aspnet/control_reqfieldvalidator.asp
This will perform validation before submitting data to server ;)
There are also other type of validator, like RangeValidator (for the need to check if the integer is between 1 and 1000).
Example:
<asp:RangeValidator ControlToValidate="youtField" MinimumValue="1" MaximumValue="1000" Type="Integer" Text="The field must be between 1 and 1000" runat="server" />
You can also add a ValidationGroup="save" for example to all your validators and to the button that user should click to save and update data.
Asp.net Have some (5 main types) server validation control's , You can use the validations for your requirement
See this image for understanding validation controls (The image referred from )
More understanding by this MSDN sit3
and here is link for all validation control sample's : click me
Here could be an example for ASP/ MVC - because you have forgotten to specify which technology from ASP. Forms or MVC ?!?
This bellow aplies to mvc and the other attributes are allready defined by the users before me.
Note that the RemoteAttribute can verify a function (validation function) .
namespace ModelValidation.Models {
public class Appointment {
[Required]
[StringLength(10, MinimumLength = 3)]
public string ClientName { get; set; }
[DataType(DataType.Date)]
[Remote("ValidateDate", "Home")]
public DateTime Date { get; set; }
public bool TermsAccepted { get; set; }
}
}
To apply validation on a model property that describes a TextBox, then a good proactice is to use TextBoxFor<>(). Like that:
#Html.TextBoxFor((model) => model.ClientName )
You can clear all your controls values by either redirecting to user to another page telling him that form is submitted, New Registration button to redirect user again to Registration page, However if you don't want that you can pick up each control and reset them either in Cs.file or using javascript,
foreach (Control ctrl in form1.Controls)
{
if (ctrl is TextBox)
{
TextBox tb = (TextBox)ctrl;
tb.Text = string.Empty;
}
else if (ctrl is DropDownList)
{
DropDownList dl = (DropDownList)ctrl;
dl.SelectedIndex = 0;
}
else if (ctrl is CheckBox)
{
CheckBox cb = (CheckBox)ctrl;
cb.Checked = false;
}
}
For your validation purpose i strongly suggest you to read about validation in Asp.net , here is a good tutorial you can learn from here
To clear all textbox you can try something like this
foreach (var item in Page.Controls)
{
if (item is TextBox)
{
((TextBox)item).Text = "";
}
if (item is DropDownList)
{
((DropDownList)item).SelectedIndex= 0;
}
//and the other types
}
For the part of validation you have to set the validation fields that you desire and bind it to the field directly on the .aspx page
<asp:textbox ID="Name" runat="server" TabIndex="1"/>
<asp:RequiredFieldValidator ID="rfvName" ControlToValidate="Name" runat="server" ErrorMessage="Name is required">
<asp:ValidationSummary ID="ValidationSummary1" runat="server" DisplayMode ="BulletList" ShowSummary ="true" HeaderText="Errors:" />
When you try to save and one of the condition of your validators returns false, the validation summary will show all the errors written in the errormessage attribute.

FindControl returns null

I am working on a solution in C# and ASP.NET 4.0 I am trying to get the value of a radiobutton from my page that was dynamically created based on some database information.
Here is what gets generated in the page source:
<td>
<input id="masterMain_3Answer_0" type="radio" name="ctl00$masterMain$3Answer"
value="Y" onclick="return answeredyes(3);" />
<label for="masterMain_3Answer_0">Y</label>
</td>
<td>
<input id="masterMain_3Answer_1" type="radio" name="ctl00$masterMain$3Answer"
value="N" onclick="return answeredno(3,'desc');" />
<label for="masterMain_3Answer_1">N</label>
</td>
Inside the OnClick function of my submit button I want to gather wether Y or N has been selected based on the user's input.
Here is what I have written so far:
RadioButton _rbAnswer = new RadioButton();
RadioButtonList _rbList = new RadioButtonList();
ContentPlaceHolder cp = (ContentPlaceHolder)Master.FindControl("masterMain");
_rbAnswer = (RadioButton)Master.FindControl("masterMain_3Answer_0");
HtmlInputRadioButton rb = (HtmlInputRadioButton)Master.FindControl("masterMain_3Answer_0");
_rbAnswer = (RadioButton)cp.FindControl("masterMain_3Answer_0");
_rbList = (RadioButtonList)cp.FindControl("masterMain_3Answer_0");
I am able to get the ContentPlaceHolder without any issues but the rest of the objects are null after it attempts to get the . I have also attempted removing the "masterMain_" but still doesn't want to find the controls.
Here is the code in which the individual radiobuttonlists are added
TableRow _tempRow = new TableRow();
TableCell _cellOK = new TableCell();
RadioButtonList _rbList = new RadioButtonList();
_rbList.ID = r[0].ToString()+"Answer";
_rbList.RepeatDirection = RepeatDirection.Horizontal;
//add options for yes or no
ListItem _liOk = new ListItem();
_liOk.Value = "Y";
ListItem _linotOk = new ListItem();
_linotOk.Value = "N";
_rbList.Items.Add(_linotOk);
//add cell to row
_rbList.Items.Add(_liOk);
_cellOK.Controls.Add(_rbList);
_tempRow.Cells.Add(_cellOK);
//add the row to the table
stdtable.Rows.Add(_tempRow);
To be able to quickly find dynamically created controls, add a dictionary to your page class:
private Dictionary<string, Control> fDynamicControls = new Dictionary<string, Control>();
then when a new control is created in code and its ID is assigned:
fDynamicControls.Add(newControl.ID, newControl);
and when you need control's reference:
Control c = fDynamicControls["controlIdThatYouKnow"];
When using FindControl don't use the id that's generated by the page. Use the ID that you specified inthe aspx.
If this is inside a Repeateror another DataBound control, you have to first find the current record. (GridViewRow or RepeaterItem) first, an use that item's .FindControl function.
See this (different - not duplicate) question to see a code example of how to do it: How to find control with in repeater on button click event and repeater is placed with in gridview in asp.net C#
When you create dynamic controller give specific ids for them. This facilitate to generate controls with our own id. therefore then we can access the controls with this id.
And also use OnInit life cycle event to generate dynamic controllers, this is the best place to generate them.
RadioButton _rbAnswer = new RadioButton();
_rbAnswer.ID="ranswerid";
Given your update, you'll find that your control heirarchy is fairly deep. You have a RadioButtonList inside a cell inside a row inside a table ...
FindControl is a method that needs to be called on a specific object and can only find objects that are actual children of that object. In this case, you either need to build a recursive method or go directly to the control in question. Since so many of these controls are generated dynamically, you'll have no real way of accessing them directly so building the recursive function may be simplest. However, on very large pages this method can be very resource consuming:
public static WebUserControl FindControlRecursive(this WebUserControl source, string name)
{
if (source.ID.Equals(name, StringComparison.Ordinal))
return source;
if (!source.Controls.Any()) return null;
if (source.Controls.Any(x => x.ID.Equals(name, StringComparison.Ordinal))
return source.FindControl(name);
WebUserControl result = null;
// If it falls through to this point then it
// didn't find it at the current level
foreach(WebUserControl ctrl in source.Controls)
{
result = ctrl.FindControlRecursive(name);
if (result != null)
return result;
}
// If it falls through to this point it didn't find it
return null;
}
This is an extension method that would allow you to call this on your ContentPlaceHolder control:
var _cp = (ContentPlaceHolder)Master.FindControl("masterMain");
RadioButtonList _rbList = _cp.FindControlRecursive("3Answer");
if (_rbList != null)
// ... Found it
Note: Treat the above as psuedo-code. It has not be implemented by me anywhere so may (likely) require tweaking to behave exactly right.

Categories

Resources