I would like to dynamically add fields to an ASP.NET MVC form with JQuery.
Example:
<script language="javascript" type="text/javascript">
var widgets;
$(document).ready(function() {
widgets = 0;
AddWidget();
});
function AddWidget() {
$('#widgets').append("<li><input type='text' name='widget" + widgets + "'/></li>");
widgets++;
}
</script>
<ul id="widgets">
</ul>
This works, but I was going to manually iterate the form values in the controller:
[AcceptVerbs("Post")]
public ActionResult AddWidget(FormCollection form)
{
foreach (string s in form)
{
string t = form[s];
}
return RedirectToAction("ActionName");
}
But it occurred to me when I send the user back to the Get Action in the Controller I will have to set the FormData with the values entered and then iteratively add the widgets with <% scripting.
What is the est way to do this in the current release (5 I believe)?
My solution could be something like this (pseudo-code):
<script language="javascript" type="text/javascript">
var widgets;
$(document).ready(function() {
widgets = 0;
<% for each value in ViewData("WidgetValues") %>
AddWidget(<%= value %>);
<% next %>
});
function AddWidget( value ) {
$('#widgets').append("<li><input type='text' name='widget" + widgets +
"'>" + value + "</input></li>");
widgets++;
}
</script>
<ul id="widgets">
</ul>
And in the controller:
[AcceptVerbs("Post")]
public ActionResult AddWidget(FormCollection form)
{
dim collValues as new Collection;
foreach (string s in form)
{
string t = form[s];
collValues.add( t )
}
ViewData("WidgetValues") = collValues;
return RedirectToAction("ActionName");
}
You can work out the details later
(sorry for mixing VB with C#, I'm a VB guy)
i might be missing the point here, but, do you need to actually post the data back to the controller via a form action? why not make an ajax call using jquery to post the data to the controller...or better yet a web service? send the data async and no need to rebuild the view with the data values sent in.
This works fine if the values are being consumed and never used again, however, if you plan on persisting the data and surfacing it through a the view, your model should really support the data structure. maybe a Dictionary<string, string> on the model.
I'm not a ASP.net developer but I know from PHP that you can use arrays as names for input fields
Ex:
<input type="text" name="widgets[]" />
<input type="text" name="widgets[]" />
You can then iterate through the post variable widgets as if it was an array of values.
No messing around with dynamicaly named variables etc.
As far as I understand the problem is to preserve the posted values in widgets.
I thik you can just render those widgest you wont to populate on the server during the View rendering.
Related
I need to pass some information from the View to the Controller.
Currently, I am doing something like the following:
var url = '#Url.Action((object)#ViewBag.CompID, "Print", "DataRecords")' + '?location=' + model.Location + '&startDate=' + model.StartDateTime + '&endDate=' + model.EndDateTime;
window.location.href = url;
I wanted to hide the location, startdate and end date from showing up in the browser url.
I was thinking about creating a model as shown below and sending the model to the Controller but not sure how to.
var model = {
Location: $('#Location :selected').val(),
StartDateTime: $("#StartDate").val(),
EndDateTime: $("#EndDate").val()
};
Note that in my case, I do not need to retrieve any data back as the Print method will do the printing.
I am open to accomplishing this besides using
window.location.href
How can this be done using AJAX as I do not need to return back to the view with any data as the Print method action will print the the appropriate view.
If you want to pass data from the front end to the back-end controller, you have two ways:
through a GET(passing parameters on the URL)
with a POST that you can do it via AJAX or simply putting your information inside a form with POST action to the method you want to hit in the controller
MVC will do the binding for you, all the information using the POST, for example, should be inside the form, then on the controller, you can create your model as the input and use the default MVC bindings.
My suggestion if you want to hide that information from the url is to do it via a post(inside a form with a submit), but anyways if you click on the Network tab of the browser in both cases you should see the parameters you are passing to your controller.
There are other ways to achieve the same thing as the use of the TempData dictionary, which keeps information for a roundtrip operation between the controller and the view, but I don't recommend to proceed this way, every time I use that as a backdoor to patch my problems I feel guilty
You can do this.
Controller
public class HomeController : Controller
{
public ActionResult HideQueryString()
{
return View("Tut143");
}
public ActionResult Print(string location, string startDate, string endDate)
{
//print here
return RedirectToAction("HideQueryString");
}
public ActionResult Tut143()
{
return View();
}
View:
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Tut143</title>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(function () {
$("#theButton").click(function () {
var model = {
Location: $('#Location :selected').val(),
StartDateTime: $("#StartDate").val(),
EndDateTime: $("#EndDate").val()
};
var url = '#Url.Action("Print", "Home")' + '?location=' + model.Location + '&startDate=' + model.StartDateTime + '&endDate=' + model.EndDateTime;
window.location.href = url;
})
})
</script>
</head>
<body>
<div>
<select id="Location">
<option value="Arizona">Arizona</option>
<option value="California">California</option>
<option value="Wyoming">Wyoming</option>
<option value="Delaware">Delaware</option>
</select>
<input id="StartDate" type="text" value="default startdate value" />
<input id="EndDate" type="text" value="default enddate value" />
<input id="theButton" type="button" value="Go" />
</div>
</body>
</html>
In View, the user will check 1 or more names from what's displayed ...
<form name=chkAttend method=post onsubmit='return validate(this)'>
<div>
#if (Model.evModel.Participants != null)
{
foreach (var fi in Model.evModel.Participants)
{
<div>
#if (#fi.AttendedFlag != true)
{
<input type="checkbox" id="c_#fi.EnrollmentId" name="MyCheckboxes" value="#fi.EnrollmentId" />
<label for="c_#fi.EnrollmentId" aria-multiselectable="True"></label>
<span></span> #fi.EnrollmentId #fi.ParticipantName
}
</div>
}
}
<input type=submit value="Confirm Attendance">
</div>
</form>
After selecting names, call the function to identify which names checked. The checked names only need to be passed to the controller. The problem - I'm getting the error message: Error 49 The name 'id' does not exist in the current context
function validate(form) {
var id = ""
for (var i = 0; i < document.chkAttend.MyCheckboxes.length; i++)
{
if (document.chkAttend.MyCheckboxes[i].checked)
id += document.chkAttend.MyCheckboxes[i].value + ","
}
if (id == "")
{
alert("Place a check mark next to event's Participant")
}
else
{
#Html.Action("ConfirmAttendance", "Admin", new { eventid = #Model.evModel.Id, enrollid =id })
}
return false;
}
How do I pass ONLY the checked items as parameter for the function in my controller?
You cannot inject a server-side partial view into your code like that. As it stands (if you got around the id variable reference problem) you would literally inject a partial view inline into your Javascript which will create invalid Javascript!
Instead treat the JS as client-side only and feed information into the page that the Javascript will need in a way that is easy to access. You can inject global variables via injected JS code, but I strongly advise against that practice.
Instead your MVC page could inject the controller action URL and the event id as data- attributes like this:
<form name="chkAttend" method="post"
data-action="#Url.Content("~/Admin/ConfirmAttendance")"
data-eventid="#Model.evModel.Id">
Using Url.Content will ensure the URL is always site relative, even when hosted as a virtual application.
Your client-side code can then pick up the values from the form, add the selected id and call the server action using Ajax:
e.g.
function validate(form) {
var action = $(form).data('action');
var eventId = $(form).data('eventid');
The fun begins now because you need to call the server from the client-side, e.g. via Ajax, with your selected option and do something with the result to change the display.
$.ajax({
// Use constructed URL (action + event id + id)
url: action + "?eventid=" + eventId + "&enrollid=" + id,
type: "PUT"
success: function (data){
// Do something with the server result
}
});
You do not show your controller's ConfirmAttendance action so I cannot even guess what you are returning. Make sure it is suitable (could be as simple as a Boolean result or as complex as a partial view to insert into the page).
I am trying to set up a simple login html page, whose action is sent to mvc controller on another of my sites. I have no problem setting up the page to do the post, and in the mvc controller I have my method that reads the form post. The problem is that I am not seeing my fields from the html form in the form collection.
Is there something special that I need to do to read a form post within a mvc controller method, if so what is that?
The is the form action markup from my page
<form action="http://reconciliation-local.sidw.com/login/launch" method="post">
User Name <input type="text" id="username"/><br/>
Password <input type="text" id="password"/>
<input type="submit" value="launch"/>
</form>
The controller method
[HttpPost]
public ActionResult launch(FormCollection fc)
{
foreach (string fd in fc)
{
ViewData[fd] = fc[fd];
}
return View();
}
When I step through the controller method code, I am not seeing anything in the formcollection parameter.
Post Html To MVC Controller
Create HTML page with form (don't forget to reference a Jquery.js)
<form id="myform" action="rec/recieveData" method="post">
User Name <input type="text" id="username" name="UserName" /><br />
Password <input type="text" id="password" name="Password"/>
<input type="submit" id="btn1" value="send" />
</form>
<script>
$(document).ready(function () {
//get button by ID
$('#btn1').submit(function () {
//call a function with parameters
$.ajax({
url: 'rec/recieveData', //(rec)= Controller's-name
//(recieveData) = Action's method name
type: 'POST',
timeout: '12000', (optional 12 seconds)
datatype: 'text',
data: {
//Get the input from Document Object Model
//by their ID
username: myform.username.value,
password: myform.password.value,
}
});
});
});
</script>
Then in The MVC Controller
controller/action
| |
1. Create Controller named rec (rec/recieveData)
Create View named rec.cshtml
Here is the controller:
public class recController : Controller
{
// GET: rec
string firstname = "";
string lastname = "";
List<string> myList = new List<string>();
public ActionResult recieveData(FormCollection fc)
{
//Recieve a posted form's values from parameter fc
firstname = fc[0].ToString(); //user
lastname = fc[1].ToString(); //pass
//optional: add these values to List
myList.Add(firstname);
myList.Add(lastname);
//Importan:
//These 2 values will be return with the below view
//using ViewData[""]object...
ViewData["Username"] = myList[0];
ViewData["Password"] = myList[1];
//let's Invoke view named rec.cshtml
// Optionaly we will pass myList to the view
// as object-model parameter, it will still work without it thought
return View("rec",myList);
}
}
Here is the View:
#{
ViewBag.Title = "rec";
}
<h2>Hello from server</h2>
<div>
#ViewData["Username"]<br /> <!--will display a username-->
#ViewData["Password"] <!-- will display a password-->
</div>
If you posted some code it would be much easier to help you, so please edit your question...
Make sure that your form's action has the correct address, that your method is specifying POST (method="POST") and that the input fields under your form have name attributes specified.
On the server side, try making your only parameter a FormCollection and test that the fields in your form posted through the debugger. Perhaps your model binding isn't correct and the FormCollection will at least show you what got posted, if anything.
These are just common issues I've seen. Your problem could be different, but we need to see what you're working with to be able to tell.
Try something like this:
cQuery _aRec = new cQuery();
_aRec.Sqlstring = "SELECT * FROM Admins";
DataSet aDS = _aRec.SelectStatement();
DataTable aDT = aDS.Tables[0];
foreach (DataRow aDR in aDT.Rows){
if (txtAdminUsername.Text == aDR[0].ToString()){
if (txtAdminPassword.Text == aDR[1].ToString()){
Session["adminId"] = aDR[0];
Response.Redirect("Admin.aspx");
return;
}
}
}
Make sure that your FormCollection object properties for username and password are defined properly.
I had to use the name attribute on the text tag, and that solved my problem, is now working like a charm.
You have to use Ajax to do that.. Whenever you want to "submit" from client side, you should use Ajax to update the server
Step 1 - you redirect your Ajax call to your action, but with your list of parameters in the query-string appended
$.ajax(url: url + "?" + your_query_string_parameter_list_you_want_to_pass)
Step 2 - add optional parameters to your Controller-action with the same names and types you expect to get returned by the client
public ActionResult MyControllerAjaxResponseMethod(type1 para1 = null,
type2 para2 = null,
type3 para3 = null, ..)
Know that the optional parameters have to be initialized, otherwise the Action itself will always ask for those
Here's where the "magic" happens though --> MVC will automatically convert the query-string parameters into your optional controller-parameters if they match by name
I was also looking for a good answer for this, --> i.e. - one that doesn't use q-s for that usage, but couldn't find one..
Kinda makes sense you can't do it in any other way except by the url though..
My content will be edited number of times.So i need to store result html to database and load it again when it is neccessary.Here is my current start implementation:
#using (#Html.BeginForm("EditArticle", "Admin", new { id = ViewData["id"] }))
{
<div id="editor"> </div>
<input type="submit" value="save changes" onclick = "setValue()" />
<input type ="hidden" id="value" name="html" />
}
<script>
var editor, html = 'Model.Text';
function createEditor() {
if (editor)
return;
var config = { width:"900px"};
editor = CKEDITOR.appendTo('editor', config,html);
}
function setValue() {
$("#value").val(editor.getData());
}
createEditor();
</script>
But I get eror with initialization html variable.So, could anyone show how correct encode / decode html?
EDIT
Here is data controller receives:
html = <p>ARTICLE 3</p>\r\n
Values like this I store in database and try insert again.
First things first, to fix your code syntactically, it should probably read something like:
var editor, html = '#Html.Raw(Model.Text)';
However, why not instead of dealing with the markup in JavaScript and having to escape and unescape it, dump it directly where it should go i.e.
<textarea name="editor1">#Html.Raw(Model.Text)</textarea>
<script>
CKEDITOR.replace( 'editor1' );
</script>
And then transform that textarea into your ckEditor? As per their basic example here: http://docs.ckeditor.com/#!/guide/dev_framed
Secondly, aside from that I am not sure what errors you are receiving with your controller, so you will have to post further details for me to help you beyond the above.
I hope this helps.
I have a list of Payees in a drop down box on my form. I would like to populate a different drop down, based on the selected item of the Payee drop down, without post backs and all that.
So, I created a method in my controller that does the work:
private JsonResult GetCategories(int payeeId)
{
List<CategoryDto> cats = Services.CategoryServices.GetCategoriesByPayeeId(payeeId);
List<SelectListItem> items = new List<SelectListItem>();
foreach(var cat in cats)
{
items.Add(new SelectListItem {Text = cat.Description, Value = cat.CategoryId.ToString()});
}
return Json(items);
}
Now, I am unsure what to add to my view to get this to work.
At the moment, all I have is this:
<% using (Html.BeginForm())
{%>
<p>
<%=Html.DropDownList("SelectedAccountId", Model.Accounts, "Select One..", null) %>
</p>
<p>
<%=Html.DropDownList("SelectedPayeeId", Model.Payees, "Select One...", null) %>
</p>
<input type="submit" value="Save" />
<%
}%>
they populate fine... so when the user selects the SelectedPayeeId drop down, it should then populate a new (Yet to be created?) drop down which holds categories, based on the SelectedPayeeId.
So, I think I need to create a JQuery function (Never done JQuery.. so not even sure where it goes) which monitors the Payee drop down for an onChange event? And then call the method I created above. Does this sound right, and if so, can you guide me in how to achieve this?
Your reasoning so far is totally sound. First you are going to want to include the jquery library in your View / Master. You can download a copy of jquery from http://jquery.com/. Add the file to you project and include a <script src="/path/to/jquery.js"> to the <head> of your document. You are going to want to add another dropdown to your View (and probably another property to your model). We'll call this 'SelectedCategoryId:'
<%=Html.DropDownList("SelectedCategoryId", null, "Select One...", new { style = "display:none;"}) %>
We've set the style of this Drop Down to not be visible initially because there is nothing to select inside of it. We'll show it later after we generate some content for it. Now, somewhere on your page you will want to include a <script> block that will look something like this:
$(document).ready(function() { $('#SelectedPayeeId').change(function() {
$.ajax({
type: 'POST',
url: urlToYourControllerAction,
data: { payeeId: $(this).val() },
success: function(data) {
var markup = '';
for (var x = 0; x < data.length; x++ ) {
markup += '<option value="' + data[x].Value + '">'+data[x].Text+'</option>';
}
$('#SelectedCategoryId').html(markup).show();
}
}); }); });
This code binds the anonymous function written above to the DOM element with the ID of 'SelectedPayeeId' (in this case your dropdown). The function performs an AJAX call to the url of your method. When it receives the results of the request (your JSON you returned) we iterate over the array and build a string of the html we want to inject into our document. Finally we insert the html into the 'SelectedCategoryId' element, and change the style of the element so it is visible to the user.
Note that I haven't run this code, but it should be (almost) what you need. jQuery's documentation is available at http://docs.jquery.com/Main_Page and the functions I used above are referenced here:
.ready()
.change()
jQuery.ajax()
.html()
.show()
You'd need to make the GetCategories as a public method as it would correspond to an action handler in your controller.
Your jquery code can look like:
<script type="text/javascript">
$(function() {
$('#SelectedPayeeId').change(function() {
$.get('<%= Url.Action("GetCategories", "YourControllerName") %>',
{payeeId: $(this).val()},
function(data) {
populateSelectWith($("#Category"), data);
});
});
//Place populateSelectWith method here
});
</script>
The populateSelectWith can fill your dropdown with data like:
function populateSelectWith($select, data) {
$select.html('');
$select.append($('<option></option>').val('').html("MYDEFAULT VALUE"));
for (var index = 0; index < data.length; index++) {
var option = data[index];
$select.append($('<option></option>').html(option));
}
}
I have not tested this code, but I am hoping it runs okay.
You can find syntax for the jquery ajax get here
Since you are not posting any data to the server, you can might as well decorate your controller action with a [HttpGet] attribute