I have a requirement for multiple tasks to be populated dynamically in response to a user 'add task' button. I don't know how many tasks will be created by the user and would prefer not to set a maximum number with hidden fields as this would be inefficient with regards to database storage space.
Tasks can be thought of as child elements to notes and are stored in separate tables. I've managed to display multiple tasks on the view but I'm less confident with front-end development and am unsure of how I can add an input field without calling a post-back, thus entering 'mid-stream save' territory..
<html>
<div class="container">
<!-- #using(Html.BeginForm()) { -->
<div>
<label asp-for="Note">Note</label>
<input id="Note" />
<span asp-validation-for="Note"></span>
<label asp-for="Task">Task</label>
<input id="Task" />
<span asp-validation-for="Task"></span>
</div>
<div>
<button type="button">Add Task</button>
<input type="submit" value="Save" />
</div>
<!-- } -->
</div>
</html>
I have also made a small jQuery function that can create task inputs upon the 'add task' button, but with little success in connecting it to the controller/model.
I've had AJAX with JSON recommended to address this requirement but I'm unsure of how this can be implemented in a form and how this can then be read by the controller and ultimately the model?
I'm open to design alternatives, should it better suit my solution.
Ok, I'll try to explain here the approach I usually use to this type of problems, after quite a while developing different applications it finished as one of my favorites.
First of all, If I'm understanding you well, you have a view where a form is build, as a part of a client interaction you need to inject elements that depends on the main entity of your form (usually as a one to many relationship). I will call those "subforms" during this answer.
You need to:
A) Manage client interaction with the elements added/modified/replaced
B) Send the final data to your server's controller so data can be persisted into database.
My approach to this type of situations is try to manage all the client interactions in the client, sending final data only on the end, after user pushes "Save" button.
Obviously... this is not valid for EVERY situation, as sometimes specific requirements could make this solution not recommended.
For the client part:
I build the core of the form on a normal way, through a standard view, usually I place specific containers to inject there the information of the "dynamic" data.
On the "Add task" button I add a listener that creates the HTML for one element of the subform and appends it to the container. Usually this code includes a delete button to eliminate it from the DOM as a whole. I also have a listener to manage those interactions.
Ok... so you now have a form where some buttons can add and remove small parts of code that represents individual elements of your subform.
Include in your client code a data structure (I usually use a JSON object) that represents a list of elements of the subform.
When your user hits the "Save" button, capture the event and, before sending data back to server make this two things:
Loop through your subform structure reading the info that it contains at this moment and store it in your client data structure (the JSON object I refer before). Now you have a JSON object with all your subform information.
Stringify it and store it in a hidden text component which is sent within the form. All of your "subform" fields could be outside of the form, as they doesn't need to be sent, the info travels back to the server in a "class instance" as a JSON structure.
In the server:
When your controller receives your form data, there will be a field which stores a string representing the whole info your user sent through the "subform".
Now you just need to get this info and manage it in the way you like. You can, for example, design a class to load this type of info and send it to the database through your usual persistence engine.
Keep in mind that in this package you are storing not only the elements added, you also have the elements that have been changed since the last edit, so you will probably have to look for them in the database and modify them.
This is quite a wall of text, and probably it's less clear to understand the idea than it's on my mind, so feel free to ask if you don't understand something or there is anything that is not clear enough.
Related
The client should be able to send everything with a button, so I can do the following:
Send everything as form fields named like invoiceId_detail_text where invoiceId would be the id of the invoice, detail the part, and text the kind of field.
Example:
<form id="invoices" name="invoice">
#foreach(var Invoce in Model.Invoices) {
<div>
<input type="number" id="#String.Format("{0}_amount", Invoice.InvoiceId)"/>
</div>
/*More Input Fields for the Invoice*/
<div>
<button type="submit"></button>
</div>
}
</form>
Or I can put every invoice separated in its own form, and send them by ajax, every form success I send the next one and so on.
Example:
#foreach(var Invoice in Model.Invoices) {
string formName = String.Format("{0}_form", Invoce.InvoceId);
<form id="#formName" class="invoiceForm" id="#formName" action="#Url.Action("EditIndividualInvoice","InvoicingEdit")">
<input type="hidden" name="InvoiceId" value="#Invoice.InvoiceId"/>
<div>
<input type="number"/>
</div>
/*More Input Fields for the Invoice*/
</form>
}
<button type="button" onclick="SendAllForms();">Send</button>
I did some research between some of my co-workers and many of them told me to just go with a post with all the invoices at the same time and then access every field by item id because I don't have knowledge of how many invoices are going to be sent, but i can get all of them by class on JQuery so it shouldn't be a problem.
I also read this article from a UX point of view and it keeps me thinking about it.
By doing it with AJAX the cliend could be able to see a loading bar and it would be great, but if he closes the page the request would be incomplete and it could be complicated.
Which option could be better and why and what are the security implications of using one over another?
I think the solution depends principally of the behavior that you wish.
By doing it with AJAX the cliend could be able to see a loading bar and it would be great, but if he closes the page the request would be incomplete and it could be complicated.
In the 2 solutions, if the user closes the page after clicking the button, this will not cancel the save. Once the request sent, it cannot be cancelled. So you shouldn't have "security" problems whatever the choosen solution.
The only thing you need to be careful, is to disable all AJAX buttons during an AJAX request, to avoid the user sending several request in the same time (that can provoke saving inconsistency data).
The classic solution is generally most simple to implement.
The AJAX solution can be most complicated to implement (more code), but provides a friendliest behavior.
I have a web app that has a form on just about every page. In order to make sure each form renders the same, as to make changes easier, I want to render all of my form controls in c# in a central place so if I need to add a class to the input or change something, I only have to do it once.
At the moment, I am just using a load of static classes like TextInputHelper, CheckboxInputHelper etc that use StringBuilder to build up the HTML and returns a string to my view.
For example, all of my forms controls are of the basic form:
<section>
<label class="label">Label Text</label>
<label class="input">
...Input Element...
</label>
</section>
What I would like to do is improve this situation as I still have a lot of duplication between the different helper classes, particularly for the wrappers to the form elements. My initial thoughts are to have a class called something like BaseFormControl that has a virtual Render method that has the outer wrapper for the control, then create other classes that implement this to do specific things like a TextFormControl that puts
<input type="text".....
inside the wrapper.
Am I on the right path for this, and/or is there a design pattern that is appropriate for what I want to do?
From my POV what I read is that you over complicating your server side just because of a CSS/HTML standardization that be easily solved from the client side.
If you still want to go for the server side approach the pattern that seems to apply to your approach is the Adapter(Wrapper) pattern meaning that you probably would want to create control wrapper clases to meet your needs for each control that renders a different html from what is offered by ASP.NET built-in controls.
If what you want to do instead is to format a group of controls then a UserControl is way much better approach.
Remember that ASP.NET was build with the spirit of trying to keep layers separated the View from the Code therefore any attempt to generate html from the server side has to be an exception and not a rule.
I have a generic 'form page' user control that we use that allows editors to insert whatever kind of html form they want to inside of it, and it handles all of the form posts.
My question is, is there a way to store the vanilla non-asp form entries in the viewstate or otherwise save the entries on a form post, in the case that some server-side validation fails, so they can be restored when the page refreshes?
We currently already do upfront javascript validation that catches the majority of the input errors. We store all the form post data in a db before we do further processing, and some of the entries contain junk (spam we wish to ignore) or only partial info (i'm assuming those are cases where the user doesn't have javascript enabled). I'm trying to catch these last fringe cases so we do not process them.
If I am understanding this correctly,
1>User fills form
2>Clicks submit
3>Error detected on the server side
4>The Html posted back should contain the form i already filled with an error message on top.
Have you considered using JQuery Ajax?
The jquery ajax will post to a web method. The web method returns a JSON response. If the response is success redirect user to the next page, else show error on top of the page.
That way you don't need to maintain the state of the user input (since it is never lost).
If you dont know what the form fields are ahead of time then I would reccomend that you look into partial postbacks.
Or else post the forms via ajax.
you could store the text HTML in
<asp:HiddenField ID="hid1" runat="server" />
this will be passed in View State
In my parent page I have a hidden control:
<input type="hidden" id="CaseID" value="" runat="server" />
I need for my page in the iFrame to be able to get this value from C# code-behind. I have so far been unsuccessful.
In the child page's code-behind I have tried variations of this:
var theParent = this.Page.Parent;
But I always get null back.
Any assistance would be greatly appreciated.
From the server's perspective, there is no relationship at all between a page which launches an iframe, and the page which is contained within that iframe. They are two completely distinct and unrelated HTTP Requests. In your code-behind, they have nothing in common and there is no way to refer to one from the other.
Thus, you'll need to use the same approach as you would if you needed to "move" data from one page to another. Two common ways (though by no means are these the only ways or even the best ways) are:
The Session object. PageABC can store a piece of data in the session, and PageXYZ can read that data from the session.
URL Parameter on the request. PageABC can call a URL (maybe even use it as the SRC of an iFrame, hint-hint) something like this: PageXYZ.aspx?someKey=someValue. PageXYZ can access URL params from the Request object (Request["someKey"])
Something else to consider: if PageABC and PageXYZ operate in conjunction with each other, maybe having them be separate pages isn't the best approach. It may make more sense for PageXYZ to actually be ControlXYZ and be contained on PageABC. It can still be presented to the user as a popup using jQuery dialogs (or using UpdatePanels and ModalPopupExtenders, if you're masochistic ;).
I want to show a pop-up on click of a button. The pop-up should have a file upload control.
I need to implement upload functionality.
The base page has nested forms. Totally three forms nested inside. If I comment the two forms then I can able to get the posted file from Request Object. But I was not suppose to comment the other two forms. With nested forms I am not getting the posted file from the Request object.
I need some protocols to implement this.
I am using C#. The pop-up was designed using jQuery.
As suggested, I am posting the sample code here.
<form id="frmMaster" name="frmMaster" method="post" action="Main.aspx" Runat="server" enctype="multipart/form-data">
<form method='Post' name='frmSub'>
<input type="hidden" name='hdnData' value=''>
</form> // This form is driven dynamically from XSL
<form method='Post' name='frmMainSub'>
<input type="hidden" name='hdnSet' value=''>
</form>
</form>
Note:
Commenting the inner forms works fine. But as it required for other functionalities not suppose to touch those forms.
I have given this code for sample purpose. The actual LOC in this page is 1200. and the second form is loaded with lots of controls dynamically. I have been asked not to touch the existing forms. Is it possible to do this functionality with nested forms?
You can have multiple HTML form tags in a page, but they cannot be nested within one another. You will need to remove the nesting for this to work. If you post some of your code, you're likely to get more help with some specific recommendations to address this.
From your posted code, it's also unclear why you'd even be tempted to use multiple forms. Can you elaborate on why you think you need multiple forms here? You don't have explicit actions in your subforms, so it's hard to tell where you want them to post, but I'm guessing it's all posting to the same page. So, why multiple forms at all?
You could always try putting one of the inner forms onto another page and serving it up in an iframe. That way the inner form is not technically inside the outer form. This will require you to alter some of the html, but there's really no way around that.
In your situation you're looking at a hack no matter how you put it. You aren't supposed to have nested forms.
Since you're using Javascript to do this, you could try moving the form element that is posting back out of the parent forms and then performing the .submit() action after it's been moved.
It's a ugly hack - but I so is the HTML -- :) (I kid, I kid!)