Let's say I have a div like this:
<div id ="carmodel"></div>
This div gets populated using Javascript 5 seconds after pageload, so it will look like this:
<div id ="carmodel">Audi A4</div>
Now I need to send the text inside the "Carmodel" div to the controller when a form is submitted.
#using (Html.BeginForm("Method", "Controller"))
{
#Html.TextBox("textbox1", "")
#Html.TextBox("textbox2", "")
<input type="submit" value="Subtmit"/>
}
I thought about using a hidden field and posting it together, but I don't know how to populate the hidden field with the text in "Carmodel" div:
#Html.Hidden("carmodelhiden", "");
It seems as if I need to use JQuery to retrieve the text like this:
var value = $("#carmodel").text();
But how do I then send this to the controller?
I also thought about using .ajax to post it but not sure how to handle the value in the controller once it's there, since the ajax method in the controller would be separate from where the form gets posted.
Anybody have any advice?
You need to set the value of the hidden input:
$('#carModelHidden').val(...);
Make sure to put the hidden value between the form using statement. Also, use a strongly typed view to bind with a property in your model.
#using (Html.BeginForm("Method", "Controller"))
{
<div id ="carmodel">
#Html.HiddenFor(model => model.SomeProperty)
</div>
}
#section scripts{
<script>
// Hook into some event and set:
$('#carModelHidden').val(...);
</script>
}
Related
I have a view where an user can trigger an action that will insert input tags in the page:
The 'Add more' button is tied to a jquery click event.
HTML:
<div id="details">
<label>More details</label>
<input placeholder="Foo" asp-for="">
<input placeholder="Bar" asp-for="">
</div>
<button id="add-details" type="button">Add more</button>
JS:
$("#add-details").click(function(){
$("#details").append(`<input placeholder="Foo" asp-for="">
<input placeholder="Bar" asp-for="">`)
});
Now, I want to bind the <input> tags to a C# Model, in order to retrieve their values in a Controller. But there could be any amount of these tags.
The most convenient way to retrieve them would be as a Dictionary<T>, but I don't know what to put in the asp-for attributes.
So how should my Model look like? What should I put in my asp-for attributes?
Although this answer is not about TagHelpers (which you are using), please read it to give you a background of what you need to do and why.
In your case you will want to add input tags so their names are array-like with indices. For example, below:
<input placeholder="Foo" asp-for="[0].Foo">
<input placeholder="Foo" asp-for="[1].Foo">
will map to a collection and the first item's (index 0) will be the contents of the input tag with asp-for="[0].Foo" and the second item's will be the contents of the input tag with asp-for="[1].Foo".
You controller action method should accept a collection. For example, if you were adding students, then the action method may look like this:
[HttpPost]
public ActionResult Index(List<Student> students) { ... }
Finally, please refer the Expression names and Collections of the docs for more info.
I am just learning MVC and wanted to create a couple radio buttons so that I can tell what radio button user has picked and what has he typed in the text box for it. So I did this in Razor:
#using (Html.BeginForm())
{
#Html.RadioButton("rb_settingsupdate", "UpdateEmail");
#Html.RadioButton("rb_settingsupdate", "UpdateQuestions");
#Html.TextBox("userpassword")
<input type="submit" value="Submit"/>
}
Now in the Controller side I was able to use [HttpPost] on my Index method and use the FormCollection to know which radio button they have chosen and what they have typed. My problem is I don't know where to put some text for each radio button in Razor? The method #Html.RadioButton didn't have parameters for it.
How about just using the html if it is static text?
#using (Html.BeginForm())
{
#Html.RadioButton("rb_settingsupdate", "UpdateEmail"); <label>Update Email</label>
#Html.RadioButton("rb_settingsupdate", "UpdateQuestions"); <label>Update Questions</label>
#Html.TextBox("userpassword")
<input type="submit" value="Submit"/>
}
I would not do it that way if I were you. Use a model instead. But if you want to do it that way, you may do it like this:
Update Email: #Html.RadioButton("rb_settingsupdate", "UpdateEmail");
Update Questions: #Html.RadioButton("rb_settingsupdate", "UpdateQuestions");
If you want to use a model, which I encourage, here is an example.
#using (Html.BeginForm())
{
#Html.RadioButton("rb_settingsupdate", "UpdateEmail");
#Html.RadioButton("rb_settingsupdate", "UpdateQuestions");
#Html.TextBox("userpassword")
<input type="submit" value="Submit"/>
}
In your code above, the second parameter in the RadioButton function (e.g. "UpdateEmail") is the value of the radio button and that is the text that will be displayed.
If you want to display text other that that, use a label.
#Html.Label
In terms of best practices for the future once you have a better understanding of MVC, you should make use of view models and use model binding for posting instead of using the form collection. Model binding is a major strength of MVC, you should start leveraging that as soon as possible.
RadioButtons (and Checkbox as well) don't have a "Text" property, because the input type radio itselfs don't have a text property, as you can see here.
Your code will produce something like this:
<input type="radio" name="rb_settingsupdate" value="UpdateEmail">
So, you have to write a plain Text outside the element, like this:
#Html.RadioButton("rb_settingsupdate", "UpdateEmail") <label>Update Email</label>
And it will turn into this:
<input type="radio" name="rb_settingsupdate" value="UpdateEmail"> <label>Update Email</label>
If you have a Model with DataAnnotations and Display properties, you can do in this way:
#Html.RadioButtonFor(x=> x.RbSettingsUpdate, "UpdateEmail") #Html.LabelFor(x=> x.RbSettingsUpdate)
What would be the best method to transfer data from one view to another view? or is this bad practice?
The reason is that i want to display #model.count() from one view to the homepage, basically a summary of all the views on the homepage. There is tempdata, html.helper etc but id like to know the best and most reliable method. Thus avoiding problems further on down the line
here is the code in question
product.cshtml
<p>Total amount of Products = #Model.Count()</p>
i basically want that same value to display on the homepage
You'd have to refresh the homepage for the value to actually 'update.' At that point you may as well pass the value back in as a parameter, but I think that's not what you're hoping for.
It probably isn't the cleanest solution, but I would think you'd want your text on the main page to be settable via some javascript/jquery.
Main Page has this snippet:
<form id="PassBackVals"
<input type="hidden" name="ProductCount" value="0">
</form>
<script>$( ".ProductCount" ).change(function() {
$("$CurrentProductCount").text = $(".ProductCount").val;
});
</script>
and the Area displaying the text itself on the main would have something along the lines of
<p> I'm currently showing <div id="CurrentProductCount">0</div> Products </p>
Then in your product.cshtml, you'd have
<script>$(".ProductCount").val = #Model.Count()
$( ".ProductCount" ).change();
</script>
Ok i looked into other methods and resolved the issue by moving the code behind the viewbag into a public method below
[OutputCache(NoStore = true, Location = OutputCacheLocation.Client, Duration = 10)]
public ActionResult UpdateTotals()
{
JobController j = new JobController();
ViewBag.JobCount = j.JobCount();
ProductController p = new ProductController();
ViewBag.ProductCount = p.ProductCount();
return PartialView("UpdateTotals");
}
then i added the viewbags into a partial view and using setinterval() javascript,
<div id ="UpdateTotals">
#{ Html.RenderAction("UpdateTotals");}
</div>
<script>
setInterval("$('#UpdateTotals').load('/home/UpdateTotals')", 10000);
</script>
i was able to refresh the data constantly to my desire without the mess of pulling data through views via javascript.
hopefully this will help anyone in future :)
i have a list of thumbnails for the user can select one of the image.
onclick on the thumbnail open a larger image into a form.
What im trying to do now is send the id of the image selected to my controller.
Note: im using MVC 4.
how can i do that?
someone can help with this pls?
Thanks in advance:
Here is my code:
#foreach (var p in ViewBag.Images)
{
<li>
<a href="~/Files/#p.Name" onclick="swap(this); return false;">
<img src="~/Files/#p.Name"/>
</a>
</li>
}
when selected is going this img tag in my form:
<img id="main" src="" >
using this javascript for this event:
function swap(image) {
document.getElementById("main").src = image.href;
}
what i have to do now?
i trying with <input type="hidden" name="Img_Id" value="Viewbag.??????"/>
to pass this value to my controller??
First, some terminology help: You can't pass a value from the view to the controller action, the view is rendered after the controller action completes.
What you want to do is pass data from the client (web browser) to a controller action, using form fields.
In your javascript swap method, you could set the value of the Img_Id field to be the value for the selected image. When the form is submitted, the Img_Id will be posted as form data, and can be accepted as a parameter in the action.
You can use JQuery (or something else) to perform the client side actions.
Here's an example (not tested though!):
First add the ID as a data attribute on the element:
<a href="~/Files/#p.Name" data-id="#p.ID" onclick="swap(this); return false;">
Then some javascript to save that to form (using jquery here):
function swap(image) {
document.getElementById("main").src = image.href;
$("input[name='Img_Id']").val($(image).data("id"));
}
To pass a value back to your controller, you either need to submit a form, or else make an AJAX request to your controller.
In the first case, you'd need to update the value of your hidden field with javascript, and then either wait for the user to submit the form, or trigger a submit through javascript depending on what your needs are.
If you want to do an ajax request, it would be more or less the same thing, but you don't need a hidden field to store the value.
You could use jQuery in your swap function. See here for the official documentation.
If you chose to use this approach, and assuming you place your JavaScript in a separate file, then make sure you get the path for the action and controller and pass that in too.
var url = #Url.Action("Index","Home");
Therefore you may call: onclick="swap(this.id, url)"
For the site I'm currently working on, I have a list of products which I need to display in a paged list. The list needs to be used on several different pages, each of which has their own rules for how to retrieve their list of products. The list pages need to refresh with AJAX. I'm using LINQ-2-SQL to talk to the database, and MVC3/Razor as the view engine.
So far so good.
What I need help with is figuring out how to implement this. I'll explain what I've done so far, and what isn't working, and I hope someone can give me some direction of the best way to get this working, whether it be bug fixes, missing options, or a redesign. Note that the setup described above is immutable, but everything else can be altered.
For the first set of data, I have Index.cshtml. This will be a list of all products. There will be other sets (such as a list of all products in a category, but I can do the selection for that just fine), but this is the primary test case.
Currently, I have an object to represent the state of the grid: PagingData. The details of it aren't really important, but it takes an IEnumerable when first instantiated, it stores itself in HttpContext.Current.Session between requests, and it has a function that returns an IEnumerable of the products that are supposed to be on the current page. I tried it as an IQueryable<>, but that didn't work.
Currently, I am getting an IQueryable.ToList() and setting it as the data for a DataPager that's used as the Model of a Partial view called _ProductList.cshtml. _ProductList primarily consists of a pager control (another partial) and a foreach loop across the Model to display a partial for each Product.
_ProductList.cshtml:
#model PagingData
<script type="text/javascript">
$(function() {
$('#productList a.pagerControl').live('click', function() {
$('#productList').load(this.href);
return false;
});
</script>
<div id="productList">
#Html.Partial("_Pager", Model)
#foreach (var item in Model.ProductsOnPage)
{
#Html.Partial("_ProductListGridDetail", item);
}
</div>
_Pager uses: #Html.ActionLink(page.ToString(), "_ProductListSetPage", new { newPage = page }, new { #class = "pagerControl" }) to provide the links to change pages (the page variable is the number of the page to draw, from a loop).
This solution works, kindof. The problem I'm having with it is that the only way to update the PagingData with the new page is via a Controller, and each method of modifying the pager (page, # of products per page, format, sort) will need its own controller because I can't overload them. This also means _Pager produces URLs like http://localhost:52119/Product/_ProductListSetPage?newPage=3 instead of http://localhost:52119/Product.
I've tried Ajax.ActionLink(), and wrapping the whole thing in an Ajax.BeginForm(), but neither seemed to work at all. I do have the jquery.unobtrusive-ajax.js library included.
Is this approach feasible? Should I replace the PagingData object with something else entirely? I do not want the paging data in the URL if it's at all possible to avoid it.
If you don't want the page in the url you could use a <form> instead of link, like this:
#using (Html.BeginForm("Index", "Product")
{
#Html.Hidden("newPage", page)
<input type="submit" value="#page" />
}
Which should generate a form for each page with a hidden field containing the actual page number, for example:
<form action="/Product" method="post">
<input type="newPage" value="3" />
<input type="submit" value="3" />
</form>
Now all that's left is to AJAXify this form:
$(function() {
$('#productList form').live('submit', function() {
$.post(this.action, $(this).serialize(), function(result) {
$('#productList').html(result);
});
return false;
});
});
Which would invoke the Index action on ProductController:
public ActionResult Index(int? newPage)
{
var model = ... fetch the products corresponding to the given page number
return PartialView(model);
}