How to find number of elements when adding and deleting elemnts dynamically using jQuery? - asp.net

I'm working on a web application (with ASP.NET 2.0 (C#) and jQuery)
In my application we have an interface using which our employees are able to enter records of a comany. We provided the interface with basic fields, Company Name, Contact Person, phone, etc. Now as you know some companies have thier branches, some have few (1 to 10) and some have many (100-200) branches. We have also provided a dynamic interface using jQuery, which allows our employees to add branches depending on number of branches a particular company have.
For addition, we have used jQuery's append function as ..
$("#branches").append("branch html fields text liek a html input field with id 'Namebranch1' ");
Now, with adding we have also provided a button with evey branch field seprately for deleting that particular branch. For deleting I have used
$("#branch1").remove()
Let's say, I have added 5 branches, then before submitting, I feel that branch number 3 is not necessary to enter, So I have deleted that branch data.
So the process of adding and removing is as follows, we have added
1,2,3,4,5
Then, We deleted 3rd branch and now we have
1,2,4,5
Now as we have 4 elements, so whenever my user is adding or deleting a branch I am adding 1 and substracting 1 from a javascript variable respectively. And then entering that variable in a hidden field, so that when user submit data then I'll have the correct number of count that how any branches are added by the user and on the basis of this count, I know that how many times I have to run the loop to catch up all branches data seprately.
But the problem is when user submit the form then I am running a loop 4 times, what it means, I'll get data of 1,2 and 4 branches but as loop will stop when it completed 4 cycles then, data of 5th branch which is actully 4 will be missing. Because elements which will be posted when user will sibmit form are as (branchName5, branchTitle5 etc.)
I hope you guys understand what I need? Please tell me some logical solution of this problem.
Thanks

Get rid of the hidden counter variable, and just iterate through Request.Form.Keys looking for branch*. Then, you'll just process any form variables that start with branch.
class Branch { public string Name; public string Title; }
void OnLoad(EventArgs e) {
base.OnLoad(e);
var branches = new Dictionary<int, Branch>();
foreach (string key in Request.Form.Keys) {
if (!key.StartsWith("branch")) continue;
int id;
if (key.StartsWith("branchTitle")) {
id = int.Parse(key.Substring("branchTitle".Length));
branches.Ensure(i).Title = Request.Form[key];
} else if (key.StartsWith("branchName")) {
id = int.Parse(key.Substring("branchName".Length));
branches.Ensure(i).Name = Request.Form[key];
}
}
}
// Ensure extension method
T Ensure<K, T>(this Dictionary<K, T> d, K key) where T:new {
if (!d.ContainsKey(key)) {
d.Add(key, new T());
}
return d[key];
}

maybe this is a clue? in submit do ....
$('#branches').each( function (i) { this.id = 'branch' + i } );

Related

Error with creating record in EF 6 - "Cannot insert explicit value for identity column in table "Photos" when IDENTITY_INSERT is set to OFF"

I recently upgraded my application from ASP.NET MVC 3 and EF 4 to ASP.NET MVC 5 and EF 6. I have several repository functions that I'm using for CRUD functionality.
I haven't changed anything, but I'm suddenly receiving this error if I try to add a record to my entities:
Cannot insert explicit value for identity column in table "Photos" when IDENTITY_INSERT is set to OFF
Here's an example of one of these methods
public void SavePhoto(Photo photo)
{
if (photo.PhotoID == 0) // new photo
_entities.Photos.Add(photo);
else // edit photo
{
_entities.Photos.Attach(photo);
_entities.Entry(photo).State = EntityState.Modified;
}
_entities.SaveChanges();
}
The PhotoID column in my database for this table is set to be the Identity. When this worked before, it would just increment the PhotoID column value based on the last entry (as expected).
Is there a better way to do this now with EF 6?
Is your PhotoId column is "int" type and annotated with "DateGenerated identity"? If so, the following code will error. Because EF might thinking you are inserting 0 into identity column.
if (photo.PhotoID == 0) // new photo
_entities.Photos.Add(photo);
Use id == 0 to check whether it is a new photo or not is not a good practice, actually it is a "bug", because say you have 3 records in the system(which default could mean your photoid is not greater than 4), And somehow you PhotoID was manipulated as 100 in the backend, now when your code run, your code will set its state as Modified. And EF might throw error for you, or EF might try to insert it for you instead of editing.
So I would suggest to use follow code
var photo = _entities.Photos.Find(photo.PhotoId)
if (photo == null) {
//your code to add photo
}
else
{
//your code to set the the modal state to modified.
}

how to change people picker value in infopath form after every form updating

I have a state machine workflow and related task. Task can be edited until it satisfy some conditions. Task formed by infopath. These task contains one people picker field. I assign 3 fields with these values:
private void createTask_Operator_MethodInvoking(object sender, EventArgs e)
{
this.createTask_Id = Guid.NewGuid();
this.createTask_Properties.ExtendedProperties["ows_TaskDisplayName"] = "user1";
this.createTask_Properties.ExtendedProperties["ows_TaskAccountId"] = #"SP\user1";
this.createTask_Properties.ExtendedProperties["ows_TaskAccountType"] = "User";
}
It is works, I can see in my form value these user. But when I change the user(for example: "user2") and submit the form, I cannot retrieve my manually changed field value, it always returns values of "user1".
private void onTaskChanged_Operator_Invoked(object sender, ExternalDataEventArgs e)
{
this.onTaskChanged_AfterProperties = this.onTaskChanged.AfterProperties;
this.onTaskChanged_BeforeProperties = this.onTaskChanged.BeforeProperties;
// here I cannot retrieve changed field value, always returns: SP\user1
this.workflowProperties.Item["UserName"] =
this.onTaskChanged_AfterProperties.ExtendedProperties["TaskAccountId"].ToString();
this.workflowProperties.Item.Update();
}
Please, if you faced such problem, help me with that...
I'm having a little trouble understanding your problem, but here are two answers. To successfully set the value of a people picker field, you have to correctly populate all three fields: DisplayName, AccountId, and AccountType. AccountType is always "User", but the other two have to align with your AD or wherever you're getting your user data from. To get data from a people picker, the best solution often includes the double eval trick: eval(eval(person, "concat(my:AccountId, ';')"), "..") This handles multiple entries correctly, if you mean that you're only getting the first in the list.

ASP Multiselect listbox separator

I have encountered a problem and I didn't manage to find any soultions yet. Let me simplify things a bit.
I have 2 forms, the first contains an ASP ListBox with multi select mode enabled. I submit the form and in the other form I use just for testing purposes this snippet of code:
protected void Page_Load(object sender, EventArgs e)
{
foreach (string formKey in Request.Form.AllKeys)
{
if (formKey != null)
{
if (formKey.Equals("ctl00$MainContent$ListBox1"))
Label1.Text = Request.Form[formKey];
}
}
}
The problems is that the values that come from the listbox (the values that i selected in the previous form) are separated by "," for ex. "test1,test2,test3". How can i change this separator to "$" for example? I need to change it because the actual values may contain "," and i don't manualy feed them to the listbox.
I can't use any other mode of transfering this values between the form because the entire application uses this model. The values that i get are then sent to a workflow where there will be manipulated and in the workflow i need to know where each listbox item starts and ends so it must be an unique separator.
Any help is apreciated! Thank you very much
Thank you MatteKarla but unfortunately this does not solve my problem. Yes, this is a good way of transfering the values from one form to another.
However i must use the method I described above with Request form keys because the listbox is one of many others "parameters" that are generated at runtime and have their values sent to a workflow method that takes this values. And i can't afford to change that in my application.
My problem is that coma (",") separator is used by default with a multiselect listbox.
I thought that there maybe is a method to change that separator from coma to another char because the coma can also be included in the value itself and this will create confusion.
As i said if i select three values test1, test2 and test3, the result with my method will be a string looking like "test1,test2,test3". However a "test1$test2$test3" would be much better.
But I'm affraid that changing this default separator is not possbile. I must think at a method to overcome this problem like replacing before feeding the listbox all the intended coma from the values with some other char not to create confusion. But this is not a great way of doing it.
On your first page/form (First.aspx.cs) create a public property with the listbox:
public ListBox PostedListBox { get { return ListBox1; } }
Set the postback-url for the button to Second.aspx
Second page in the aspx-file after the #Page-directive add:
<%# PreviousPageType VirtualPath="~/First.aspx" %>
Then in Form_Load on Second.aspx.cs you can extract the values:
if (PreviousPage != null)
{
ListBox postedListbox = PreviousPage.PostedListBox;
foreach (var index in postedListbox.GetSelectedIndices())
{
var itemText = postedListbox.Items[index].Text;
}
}
Or you could just try to locate the control by using:
if (PreviousPage != null)
{
var control = PreviousPage.FindControl("ListBox1") as ListBox;
}
Third Edit:
You could use GetValues:
Request.Form.GetValues("ctl00$MainContent$ListBox1");
returns a string array containing each of the selected items.

Adding TextBocex, CheckBoxes on Request C#

I will be starting a project soon at my company and the client would like to have the option in the portal to add textboxes or checkboxes as an administrator,,, so for instance initially I may have something like
Name [textBox]
Phone [textBox]
So the client would like to log in as an admin and be able to add
Name [textBox]
Phone [textBox]
Receive Brochure [checkBox] //added by client.
Forget about the portal and the admin part.. what I would like to know is what would be the best way to design this (the user to be able to add elements)
Any ideas would be much appreciated
Regards
You could create an additional aspx-form in which the User (or the Admin) is able to define and create his/her own forms, you supply the Variable names and they choose to add the controls, save it in a specific scheme in the Database, e.g.
UserForm:
UserID FormID
Form:
FormID FormName
FormElement:
FormID VariableName ControlType Index
Of course this could also be done by an administrator and be visible by everyone.
To view the specific forms you could add yet another aspx-page containing the following code:
protected void Page_Load(object sender, EventArgs e)
{
//you saved the FormName or ID to Session when you accessed it
string formName = Session["FormName"].ToString();
//this handles getting the elements for this Form from DB
List<FormElement> elementList = FormElement.GetForForm(formName);
this.renderForm(elementList);
}
private void renderForm(List<FormElement> eList)
{
foreach(FormElement fe in eList)
{
//Labels left, Controls right, of course this is just a design decision
if(fe.Index%2==1)
{
Label lbl = new Label();
lbl.Text = fe.Variable;
lbl.ID = fe.ControlType + fe.Variable;
divLeft.Controls.Add(lbl);
}
else
{
dynamic ctrl = null;
switch (fe.ControlType)
{
case "TextBox":
ctrl = new TextBox();
break;
case "CheckBox":
ctrl = new CheckBox();
break;
default:
break;
}
ctrl.ID = fe.ControlType + fe.Variable;
divRight.Controls.Add(ctrl);
}
}
}
Later on after the User hitting submit you'd be able to receive the values entered into those Controls by accessing divRight.FindControl(fe.ControlType + fe.Variable) since that should be unique per Form.
This approach assumes you're using .NET 4.0 (because of dynamic), but of course you can do this just fine without it, it'll just be more code.
Please let me know if this is what you searched for or if it was helpful.
Thanks,
Dennis
From what I have done in the past where I had to create a dynamic survey based on a client needs. I had a database that contained the following tables:
Survey - stores list of client surveys.
Controls - listed the type of controls that would be needed. For example, textbox, checkbox etc.
Survey Controls - links all the controls required for a survey.
User values - stores the values entered in a controll based on the survey used.
I then added some logic to dynamically create the controls based on a survey selected by reading the values from my database.

Return unordered list from hierarchical sql data

I have table with pageId, parentPageId, title columns.
Is there a way to return unordered nested list using asp.net, cte, stored procedure, UDF... anything?
Table looks like this:
PageID ParentId Title
1 null Home
2 null Products
3 null Services
4 2 Category 1
5 2 Category 2
6 5 Subcategory 1
7 5 SubCategory 2
8 6 Third Level Category 1
...
Result should look like this:
Home
Products
Category 1
SubCategory 1
Third Level Category 1
SubCategory 2
Category 2
Services
Ideally, list should contain <a> tags as well, but I hope I can add it myself if I find a way to create <ul> list.
EDIT 1: I thought that already there is a solution for this, but it seems that there isn't. I wanted to keep it simple as possible and to escape using ASP.NET menu at any cost, because it uses tables by default. Then I have to use CSS Adapters etc.
Even if I decide to go down the "ASP.NET menu" route I was able to find only this approach: http://aspalliance.com/822 which uses DataAdapter and DataSet :(
Any more modern or efficient way?
Using linq2sql you could do:
List<PageInfo> GetHierarchicalPages()
{
var pages = myContext.PageInfos.ToList();
var parentPages = pages.Where(p=>p.ParentId == null).ToList();
foreach(var page in parentPages)
{
BuildTree(
page,
p=> p.Pages = pages.Where(child=>p.pageId == child.ParentId).ToList()
);
}
}
void BuildTree<T>(T parent, Func<T,List<T>> setAndGetChildrenFunc)
{
foreach(var child in setAndGetChildrenFunc(parent))
{
BuildTree(child, setAndGetChildrenFunc);
}
}
Assuming you define a Pages property in the PageInfo like:
public partial class PageInfo{
public List<PageInfo> Pages{get;set;}
}
The processing to get it on a hierarchy is happening on web application side, which avoids extra load on the sql server. Also note that this type of info is a perfect candidate to cache.
You can do the render as Rex mentioned. Alternatively you could expand a bit on this implementation and make it support the hierarchy interfaces and use asp.net controls.
Update 1: For the rendering variation you asked on a comment, you can:
var sb = new System.IO.StringWriter();
var writer = new HtmlTextWriter(sb);
// rex's rendering code
var html = sb.ToString();
Best practice would be to do this using IHierarchyData and IHierarchalEnumerable and DataBind to a custom control which inherits from HierarchalDataBoundControl (this is the base for controls like TreeView).
However, let's try for a quick-and-dirty, not-especially-efficient, simple example in c#:
//class to hold our object graph in memory
//this is only a good idea if you have a small number of items
//(less than a few thousand)
//if so, this is a very flexible and reusable way to represent your tree
public class Page
{
public string Title {get;set;}
public int ID {get;set;}
public Collection<Page> Pages = new Collection<Page>();
public Page FindPage(int id)
{
return FindPage(this, id);
}
private Page FindPage(Page page, int id)
{
if(page.ID == id)
{
return page;
}
Page returnPage = null;
foreach(Page child in page.Pages)
{
returnPage = child.FindPage(id);
if(returnPage != null)
{
break;
}
}
return returnPage;
}
}
//construct our object graph
DataTable data = SelectAllDataFromTable_OrderedByParentIDAscending();
List<Page> topPages = new List<Page>();
foreach(DataRow row in data.Rows)
{
Page page = new Page();
page.Title = (string)row["Title"];
page.ID = (int)row["PageID"];
if(row["ParentID"] == null)
{
topPages.Add(page);
}
else
{
int parentID = (int)row["ParentID"];
foreach(Page topPage in topPages)
{
Page parentPage = topPage.FindPage(parentID);
if(parentPage != null)
{
parentPage.Pages.Add(page);
break;
}
}
}
}
//render to page
public override void Render(HtmlTextWriter writer)
{
writer.WriteFullBeginTag("ul");
foreach(Page child in topPages)
{
RenderPage(writer, child);
}
writer.WriteEndTag("ul");
}
private void RenderPage(HtmlTextWriter writer, Page page)
{
writer.WriteFullBeginTag("li");
writer.WriteBeginTag("a");
writer.WriteAttribute("href", "url");
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(page.Title);
writer.WriteEndTag("a");
if(page.Pages.Count > 0)
{
writer.WriteFullBeginTag("ul");
foreach(Page child in page.Pages)
{
RenderPage(writer, child);
}
writer.WriteEndTag("ul");
}
writer.WriteEndTag("li");
}
This should get you started.
with x (pageID, title)
as (
select cast(title as varchar(100)),pageID
from pages
where parentID is null
union all
select cast(x.title||' - '||e.title as varchar(100)),
e.pageID
from pages e, x
where e.parentID = x.pageID
)
select title as title_tree
from x
order by 1
Output:
TITLE_TREE
Home
Products
Services
Products - Category 1
Products - Category 2
Products - Category 2 - Subcategory 1
Products - Category 2 - Subcategory 1 - Third Level Category 1
Products - Category 2 - Subcategory 2
Have you considered getting XML output from SQL Server using SELECT ... FOR XML EXPLICIT? Your data seems set up perfectly for that.
For an example:
http://www.eggheadcafe.com/articles/20030804.asp
If you want to pursue I could work through an example.
RexM - firstly I must state that I'm a front-end developer so can't even touch you for skill and knowedge of coding C#. However - I did implement your solution using the Page object and encountered a problem. Yes, sorry I'm a "pleaseSendMeTheCode" leech in this instance, but neverless, thought it was important to detail the "bug".
I'm building a site that uses a nested UL to display menu items and allows the user to re-sort the menu however they want.
My menu has the following data fields: pageID, parentID, pageOrder, pageTitle
Page order refers to the order in which the pages appear in a node.
So my query for SelectAllDataFromTable_OrderedByParentIDAscending();was:
SELECT * FROM [pages] ORDER BY [parentID] ASC, [pageOrder] ASC
I then use jsTree to make the menu items draggable and droppable.
I re-ordered a few pages and discovered a bug:
Say my structure is like so:
home
cars
usa
muscle cars
suvs
europe
colours
directions
vertical
horizontal
up
down
If I move "cars" (and all it's children) inside "down", the children of "cars" no longer display in the menu. That's the "bug".
I have checked the db and parentID and pageOrder are all correct under "cars", I also tried changing my SQL query, starting from scratch, all sorts of testing directly on the DB (all the above with jsTree turned off so I can see the basic nested UL) - but with no success.
Just wondering, as I've seen other forums pointing to this page for solutions to turning hierarchical sql data into nested UL's, it might be worth somebody looking into it.
As my whole site is based on the use of Javascript I've now implemented a Jquery.ajax solution (which, very badly commented, is on my site here) to build the nested UL but as I said, just flagging as potential problem.
Thanks very much though for a kick start in my own finding of a solution!

Resources