Similar to the "add more experience" functionality in http://careers.stackoverflow.com/cv/edit, I want to provide a "Add another location" link which should display an additional row of a set of 4 dropdowns (country, state, city, region). I'm actually using the CascadingDropDown jQuery Plugin for ASP.NET MVC (http://weblogs.asp.net/rajbk/archive/2010/05/20/cascadingdropdown-jquery-plugin-for-asp-net-mvc.aspx) for my location dropdown functionality, but I need to give the user the ability to add multiple locations. What would be the easiest way to handle this in ASP.NET MVC and jQuery?
I ended up using this: http://charlie.griefer.com/blog/index.cfm/2009/9/17/jQuery--Dynamically-Adding-Form-Elements
When I do such things I usually render PartialView's (with parameters to distinguish them) in a loop.
I keep a hidden textarea with the HTML of the elements I'm adding in it, something like:
<textarea style="display:none" id="template">
<select id="{0}_state" name="{0}_state"><options....></select>
<select id="{0}_city" name="{0}_city"><options....></select>
</textarea>
Then on the event where you want to add those elements to the form, using jQuery I do something like:
var global_number_added = 0;
var template = jQuery.format($("#template").val());
var add_this = template(global_number_added++); //something unique
add_this.appendTo("selector_to_append_the_elements_to");
Hooking it up with the plugin you are using is something you'll have to look up, but you'll probably need to tie in some events to set up the cascading drop down lists.
Hope that helps.
M
There are a lot of ways you could do this, but a pretty easy way in all asp.net is:
Put the form for each "additional row" in a UserControl
Put that section in an UpdatePanel
"Add another location" would cause an async postback to the UpdatePanel
Dynamically add an instance of the UserControl using Page.LoadControl(..) when they click Add Another.
Track the number of locations in ViewState so you know how many to render on each update.
You could also use jQuery to just copy the input form when they click "Add another," but it would be hard to make that sync up with asp.net for the postback, though not impossible, or you could just look at Request.Form to process it.
Related
I'm trying to build a very specific search page for a project and I'm having lot of trouble dealing with multiple postbacks invoked by dynamically-generated controls on a single page.
The page has to work like this:
There is a single checkbox, "Detailed search", that causes a postback on checking/unchecking.
When detailed search is not active, a simple grid with contents and buttons is displayed. Nothing special.
When detailed search is active, N checkboxes must be generated from some dynamic data, that represent the sections where you want the search to happen. Below the checkboxes, an AJAX-enabled tab control will appear, initially with no tab pages.
When checking one of the section checkboxes, a postback will occur. After the postback, data will be searched in the section selected by the user, then a new tab page containing a grid view of results and the name of the section will be added to the tab control. If the checkbox is unchecked, the tab page will disappear from the control, again, after a postback.
Now, the issue is that pretty much everything has to be generated dynamically, and that pretty much everything is connected to something else.
First issue: dealing with the "Detailed search" checkbox. Sounds easy, doesn't it? My initial idea was to set Page.Viewstate["DetailedSearchEnabled"] to true or false during the check/uncheck event handler, then create controls dynamically checking the value of DetailedSearchEnabled during Page_Load.
Nope. The postback event-handling happens between Page_Load and Page_LoadComplete. It would take an additional refresh for things to work as intended.
<< Then I'll just generate the controls on Page_LoadComplete! >>
Nope. Those controls need event handling as well, and if they're generated after Page_Load they will not be wired up correctly.
A possible solution would be generating everything in advance, on Page_Load, and only hiding/showing controls on Page_LoadComplete. But that is inefficient, and one important point of this search page is that only the minimum amount of controls should be generated.
The difficulty of this task seems to come from the way event wiring and the page life cycle work.
Surely there must be a better way of approaching this problem.
First issue: dealing with the "Detailed search" check box.
The correct approach (if you want to use page post-backs) is as follows:
In the CheckChanged event handler, save the value of the Checked property to ViewState["DetailedSearchEnabled"]. If the value is true, add the dynamic check boxes to the page. If the value is false, find and remove them.
Override LoadViewState. After calling base.LoadViewState, re-create the dynamic check boxes and wire up their events if ViewState["DetailedSearchEnabled"] is true. Note that neither Page_Load nor Page_LoadComplete is the appropriate place to do this.
Yes, you should create the dynamic check boxes at two points in the page life cycle. I recommend a helper method.
In general, your event handlers should add or remove just the dynamic controls (if any) affected by those particular events, but LoadViewState should re-create all dynamic controls that existed from the previous page request. You must store enough information in view state for LoadViewState to do so.
My answer to this other question demonstrates how to add and remove dynamic controls. You may want to use it as a reference.
Sounds to me like you should be using a CheckBoxList control to handle your dynamic checkboxes. You can add an remove items to the CheckBoxList during your post back and not have to worry about dynamically adding/removing actual controls/events to the form.
Here is a link to the msdn:
https://msdn.microsoft.com/en-us/library/14atsyf5(v=vs.85).aspx
Here is some sample code:
Protected void Button1_Click (object sender, System.EventArgs e)
{
CheckBoxList.Items.Add(new ListItem("TextValue1", "Value1"));
CheckBoxList.Items.Add(new ListItem("TextValue2", "Value2"));
}
If all else fails, you could still fall back on the quick-and-dirty old-fashioned ASP way.
Use Response.Write or <%...%> to generate your dynamic controls as plain old HTML (simple form fields, e.g. <input type="checkbox" name="foo" value="1" />).
Make sure you have a form field for every piece of information you may need after the postback(s). If necessary, use hidden form fields to 're-post' values across subsequent postbacks.
After postback, retrieve the values of the controls with the Request object.
Use those values to adjust the generation of controls as you see fit.
You should be able to do all of this in Page_Load. The advantage is total freedom. The disadvantage is total freedom to make a big mess of your aspx. So you may want to migrate all this dirty code out of your aspx, and into a custom-made control, which you can then add to your aspx.
When generating your own HTML, be careful not to introduce XSS vulnerabilities. Use HtmlEncode where necessary.
As you suggested yourself, there is a better way to tackle it.
If I was in the same situation, I would create web methods for interacting with the page, and use client side to do the UI. I'm currently working mostly with angular JS, although it does come with a learning curve. You could use ng-hide/ng-show to bind to the checkbox event to display the detailed search. When the n number of checkboxes needs to be displayed, you can then just fill them in with ng-repeat, for each of the items you need to display, after a check/uncheck you can dynamically populate new controls etc. through web method calls if extra data is needed.
Pure ASP postbacks are quite clunky from my experience, and not really suited for building a maintainable dynamic UI.
Instead of making so many postbacks, it would be better to use jquery and ajax calls to load the controls as needed and then attach events to it or you can even use UpdatePnael for that. Help Links:
https://www.simple-talk.com/dotnet/asp.net/ajax-basics-with-jquery-in-asp.net/
http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
I've been trying to iterate over a placeholder in sitecore. Essentially, there control that needs to be repeated by the page for a collection of elements (say a tab). I've only gotten the placeholder to render once. The following tabs don't have content inserted into them.
The code for something like what I'm trying to do is:
<asp:Repeater ID="rptTabs" runat="server">
<sc:Placeholder ID="plSocialSharing" runat="server" Key="Social"/>
<sc:Placeholder ID="plTab" runat="server" Key="content"/>
</asp:Repeater>
Should something like what I'm doing work? If it doesn't, do I need to user another sitecore control (something more dynamic?). Should I instead be using user controls I place there, or should I stick with the sitecore framework approach?
Since each of your tabs will contain the same rendering the I would not bother with placeholders. I think you will be adding more complexity than is required.
Assuming you are going to be using the jQuery UI Tab plugin then I would use the same technique you used in the previous question you asked, i.e. render out the content of the div tabs in the repeater, and you will need another repeater to create the ul list of the actual tabs.
Assuming you have a tree structure like:
- Social Sharing
-- Facebook
-- Twitter
-- Email
You could now Social Sharing use as the datasource of your Repeater and still allow the content of the tabs to be editable if you use Sitecore controls.
If you wanted something much more dynamic, like different rendering for each of the tabs, for example one with rich text, one with 2 column, one with table etc, then again there are a couple of ways of achieving this. One way would be to use standard <asp:PlaceHolder> in your repeater and add the rendering in this from your codebehind on ItemDataBound event.
Another option would be to add a bunch of different renderings into the placeholder in the page editor and set the datasource of each to content item. It will be difficult to use jQueryUI Tabs with this though since you would want markup like this in each control to make them self contained:
<div class="tab-title">Tab Title</div>
<div class="tab-content">Put whatever content you want in here</div>
As long as each rendering followed this structure then it would be easy to add several of these to the page and they would still be editable in the Page Editor, albeit listed one after another (not in tab format) in Editing mode. You would need to roll your own tab plugin, but it could be something as simple as:
Only in Preview or Normal mode
Get all .tab-title elements
Create a ul list and prepend to the tab container
Now call jQuery UI Tabs on the element
Hopefully given you some options at least, I can expand on any of these if it something you need but will have to get some code samples together.
I am working on a project in which on selecting a drop down list item the values from the database should appear in the respective two text boxes.
But, alongside I am placing an image which is actually getting created based on the two values. Now on selecting the next dropdownlist item there is a page refresh and the placed image dissapears.
How to I avoid the page refresh keeping in mind that the fields from the database must get displayed on the page in the two fields on select of drop down list.
Kindly help!
thanks...
In my case, there exists a table in which there are two halfs, the left has text boxes n a button n to the right side of the table the image appears.
If you are using ASP.NET WebForms, you could wrap the controls which you only wants to post back inside an UpdatePanel.
Alternatively, remove AutoPostBack="true" from your DropDownList, and use javascript/jQuery AJAX to perform your database request.
Disable autopostback.
<asp:DropDownList AutoPostBack="false" ... />
Without the slightest piece of code, this will be hard to answer.
To prevent default behavior in javascript, there is this method
e.preventDefault();
Where e is your event.
Your issue is to preserve the values fetched from DB.
The easiest and safest way is to store the values fetched from database into hidden fields. This way when your page postbacks the values persists and you can use them as you wish.
Happy Coding!!!
How would I go about using c# and ASP.NET (or Javascript if need be) to have my drop down lists change something like a div on the page. Basically I want it to populate a div with certain data.Either from a SQL or XML Data Source. I have places I wanted listed, so I'm assuming I'm going to need to put each place in with the tags that it may contain.
I would use jQuery, or some other javascript library, to hook up a listener to your dropdown and when the value changes I would make a request to some services or where you get your data from.
If you're using asp.net, then it's really straight-forward.
1) put a <asp:label> or <asp:literal> in your div.
2) in your designer, double-click your dropdownlist -- this will take you to the code-behind for the dropdown's onselecteditemchanged event.
3) Call your data, and assign it to the label. Ex.: ...me.myLabel.text = myreader("myfield"), or some more complicated html you've assembled, or what have you.
Is there a way to create a collapsible ASP.NET gridview displaying a parent child relationship based on a check box click?
An easy solution would be to wrap your GridView in an UpdatePanel, and just code everything as you would with normal postbacks. But this is a very heavy-handed approach.
Another option is to use Microsoft's AJAX Library to invoke PageMethods. See the second example here: http://www.asp.net/ajax/documentation/live/Tutorials/ExposingWebServicesToAJAXTutorial.aspx . Once the page loads, you can bind a function to the checkboxes' click events that invokes a PageMethod to inject the appropriate HTML labels and inputs into the row, with a link that passes the values from the form to a different PageMethod.
I don't think that any of the Microsoft grids can do that. However, third party grids will do this. We used ComponentArt's grid control on my last project, and used it to do exactly what you want.