I want to display a PartialView inside a View with a shared layout, the thing is that I want to render this partial from a select value.
So, I want to know how to trigger the view from Controller depending of the selected value in the select element.
Here's the code:
EDIT
Administrador.cshtml
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td>Seleccione Cartera:</td>
<td>
<select id="SeleccionCartera" name="SeleccionCartera">
<option value="">Seleccione Cartera</option>
<option value="0">Activa</option>
<option value="1">Conservadora</option>
<option value="2">Moderada</option>
<option value="3">Nueva</option>
</select>
</td>
<td>
<button name="btnBuscarRegistros" class="btnExportar">Buscar</button>
</td>
</tr>
</table>
<div id="prueba" name="prueba">
//Here is where my partial displays info.
</div>
Functions.js
$("#SeleccionCartera").change(function () {
var val = $("#SeleccionCartera").val();
$("#prueba").load('Admin/SeleccionCartera/?value =' + val);
});
AdminController.cs
public ActionResult SeleccionCartera(int id)
{
string partial = "";
if(id==3)
{
partial = "_NuevaCartera";
}
return PartialView(partial);
}
If the user select "Nueva", I want to display a PartialView, if the user choose "Activa" I want to display another PartialView (or the same) from Controller.
Thanks for the help!
PD: Sorry for my English, I'm Chilean.
There's numerous ways to do this, Here is one of them:
Set up an empty Div, and use JQuery's load function
<div id="MyPartial">
</div>
$("#MyDDL").change(function () {
var val = $("#MyDDL").val(); // this should be an int
$("#MyPartial").load('Home/ViewPartial/?value =' + val);
});
Controller
public ActionResult ViewPartial(int value)
{
// do stuff
return PartialView("_MyPartial",model);
// if you want to have a "dynamic" partial view this should work
//string partialViewName = "name";
// return PartialView(partialViewName,model);
}
an idea:
you could put your partial view within a div and give it an Id.
also, give your select control an Id.
Then create a javascript function which triggered by the onselect event of the select element.
in that js function check the selected value if it's Nueva? then make the partial view div visible if not hide the div
set the partial view div by default hidden.
please check this similar example: http://www.rajeeshcv.com/post/details/27/asp-net-mvc-conditional-rendering-partial-views
Related
I'm trying to implement a button to adding and removing a row using static HTML. I saw this question that seems to be what I want, but I found that the example doesn't work for drop-down lists. None of the drop-down lists' options ever are marked as selected. If I don't clear the model state, all of the old values are kept. How can I keep my changes to the view-model?
// Controller action
[HttpPost]
public virtual ActionResult DoSomething(DoSomethingViewModel viewModel)
{
if (viewModel != null)
{
if (viewModel.ButtonPressed != null)
{
if (viewModel.ButtonPressed.Trim() == "Cancel")
{
return Redirect(ApplicationUtilities.CancelRequestUrl);
}
else if (viewModel.ButtonPressed.Trim() == "AddRow")
{
ModelState.Clear();
// This only covers non-JavaScript users.
// One for the newest one.
viewModel.FieldOneValues.Add(String.Empty);
viewModel.FieldTwoValues.Add(String.Empty);
viewModel.FieldThreeValues.Add(null);
return View(viewModel);
}
else if (viewModel.ButtonPressed.Trim().StartsWith("Remove"))
{
ModelState.Clear();
String[] split = viewModel.ButtonPressed.Split('-');
if (split.Length == 2)
{
Int32 indexToRemove;
Regex regex = new Regex(#"\[([0-9]+)\]");
Match match = regex.Match(split[1]);
if (match.Success && Int32.TryParse(match.Groups[1].Value, out indexToRemove))
{
viewModel.FieldOneValues.RemoveAt(indexToRemove);
viewModel.FieldTwoValues.RemoveAt(indexToRemove);
viewModel.FieldThreeValues.RemoveAt(indexToRemove);
}
}
return View(viewModel);
}
}
}
if (ModelState.IsValid)
{
return WhateverIsDoneOnSuccess(viewModel);
}
else
{
return View(viewModel);
}
}
// View Model
public class DoSomethingViewModel
{
public DoSomethingViewModel()
{
this.FieldOneValues = new List<String>();
this.FieldTwoValues = new List<String>();
this.FieldThreeValues = new List<Int32?>();
}
public virtual IList<String> FieldOneValues { get; set; }
public virtual IList<String> FieldTwoValues { get; set; }
public virtual IList<Int32?> FieldThreeValues { get; set; }
public virtual String ButtonPressed { get; set; }
}
<!-- Spark View -->
<tr each="var fieldOneValue in Model.FieldOneValues">
<td headers="FieldOneTh">${Html.TextAreaFor(m => m.FieldOneValues[fieldOneValueIndex])}</td>
<td headers="FieldTwoTh">${Html.TextAreaFor(m => m.FieldTwoValues[fieldOneValueIndex])}</td>
<td headers="FieldThreeTh">
${Html.TextBoxFor(m => m.fieldOneValueIndex], new { disabled="disabled", #readonly="readonly" })}
${Html.DropDownListFor(
m => m.FieldThreeValues[fieldOneValueIndex]
, ApplicationUtilities.FieldThreeSelectListItems
, " "
)}
</td>
<td headers="AddRemoveTh">
<button name="${Html.NameFor(m => m.ButtonPressed)}" class="Remove" type="submit" value="Remove-[${fieldOneValueIndex}]">Remove</button>
<button if="fieldOneValueIsLast" name="${Html.NameFor(m => m.ButtonPressed)}" class="Add" type="submit" value="AddRow">Add</button>
</td>
</tr>
<!-- HTML Output -->
<tr>
<td headers="FieldOneTh"><textarea cols="20" id="FieldOneValues_0_" name="FieldOneValues[0]" rows="2">
</textarea></td>
<td headers="FieldTwoTh"><textarea cols="20" id="FieldTwoValues_0_" name="FieldTwoValues[0]" rows="2">
</textarea></td>
<td headers="FieldThreeTh">
<input data-val="true" data-val-number="The field Nullable`1 must be a number." disabled="disabled" id="FieldThreeValues_0_" name="FieldThreeValues[0]" readonly="readonly" type="text" value="0" />
<select id="FieldThreeValues_0_" name="FieldThreeValues[0]"><option value=""> </option>
<option value="0">Option 1</option>
<option value="1">Option 2</option>
<option value="2">Option 3option>
</select>
</td>
<td headers="AddRemoveTh">
<button name="ButtonPressed" class="Remove" type="submit" value="Remove-[0]">Remove</button>
<button name="ButtonPressed" class="Add" type="submit" value="AddRow">Add</button>
</td>
</tr>
Plus I'm curious; I think there should be a way to do this.
There is, but you have to handle the post correctly. It's situations like these why PRG (Post-Redirect-Get) is recommended. When you click something like a remove button for a particular item, it's not appropriate to save all the other fields and do whatever else would happen when the whole form is actually submitted. All the user indicated was that they wanted to remove this one item.
Therefore, when you get the post, you remove that item from the database or wherever it's persisted and then you redirect back to the original form if that's what you want. The redirect process updates the page state so that the item is now gone and the rest of the form can then be edited without carrying around stale data. What you're trying to do is remove the item, but then just return the view directly which still has the posted item in the data backing it. That's where your problem is.
I think you went down this path because you're trying to maintain any edits the user made to other areas of the form, but that's simply not going to be possible. However, you do have some options:
Don't actually have a button that removes the item right this minute. Instead, provide a checkbox or something that indicates the item should be deleted when the user posts the entire form. Then you can save the all the form data, remove the indicated items, and redirect afterwards like you should.
Use local storage to save the user's edits on the client-side, and then read them back from local storage after the page loads again, following the redirect. However, this requires JS.
Use AJAX to submit the request to remove the item, and then remove the row from the DOM. However, this requires JS.
Also, remember that it's entirely possible to progressively enhance your form. So, you can implement #1 and #3, and then if JS isn't available, #1 still serves as a fallback.
I'm starting to develope in .NET and I have some questions.
I've created a view which uploads images to Azure. This view is included in a Controller called Document.
What I want is to display this view in another controller view. The view works perfectly alone, but when I try to reference it it gives me an error which I still don't know how to solve.
This is the view "Upload.cshtml"
#{
ViewBag.Title = "Upload";
}
<p>
#using (Html.BeginForm("Upload", "Documento", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" id="fileToUpload" name="image" />
<input type="submit" id="btnSubmit" value="Upload" />
}
</p>
<ul style="list-style-type: none; padding: 0;">
#foreach (var item in Model)
{
<li>
<img src="#item" alt="images" width="100" height="100" />
<a id="#item" href="#" onclick="deleteImage('#item');">Delete</a>
</li>
}
</ul>
<script type="text/jscript">
//get file size
function deleteImage(item) {
try {
var url = "/Documento/DeleteImage";
$.post(url, { Name: item }, function (data) {
window.location.href = "/Documento/Upload";
alert(data);
});
}
catch (e) {
alert("Error is :" + e);
}
}
</script>
And this is how I try to invoke the view from another Controller Index view:
#RenderPage("~/Views/Documento/Upload.cshtml");
#RenderBody();
And the error I get is because of the "#foreach(var item in Model)" sentence.
How should I do this?
It looks like you are missing your model at the top of your view. Something like this:
#model MyProject.Models.MyModel
Secondly your foreach loop needs a IEnumerable type. Is your model IEnumerable or #Model.SomeIEnumerable?
Lastly, whatever #item is in your loop should have seperate properties for your img src and anchor id attributes.
Either your code displayed isn't complete or you have a model issue. Here is any example of how to do what I think you are looking for.
View Model
public class MyModel
{
public string ProductId {get;set;}
public string ProductSrc {get;set;}
}
View
#model IEnumerable<MyModel>
<ul>
#foreach(item in Model)
{
<li>
<img src="#item.ProductSrc" />
<a id="#item.ProductId">Delete</>
</li>
}
Move the view to the Views/Shared folder instead. Then it will be available to all controllers without having to do anything special.
Also your view obviously expects a model to be passed in, so you have to do that from both controllers using the view.
In the controller that works I assume you have something like
return View("Upload", model);
or just
return View(model);
if you're action is named Upload. In the new action that is to use the same view, you have to create the model object and pass it to the view too.
For example I have the following model which I am passing a list of to the view:
public class ExampleViewModel
{
public int id { get; set; }
public string name { get; set; }
}
In my view I have the following:
#model List<ExampleViewModel>
<table>
<tr>
<th>Name</th>
<th>Action</th>
</tr>
#foreach (var x in Model)
{
<tr>
<td>
#Html.DisplayFor(m => x.name)
</td>
<td>
<input type="button" onclick="edit();" value="Edit">
</td>
</tr>
}
</table>
<script type="text/javascript">
function edit(x) {
window.location = "/Home/Edit?id=" + x
}
</script>
What I am having trouble with is passing x.id to the edit() function. I expected:
<input type="button" onclick="edit(#x.id);" value="Edit">
to work but it did not.
Thanks
Try this
<input type="button" onclick="edit(#x.id);" value="Edit">
I'd recommend you to use data slash atributes, and use something like jQuery to handle events, and use the data slash attributes.
A data slash attribute is simply an attribute whose name starts with "data-". You can define as many of theses attributes as you need, on any element, an all browsers will support them.
<input type="button" onclick="edit" data-id="#x.id" value="Edit">
When the edit method is executed, you can access the element (using this), and them with jQuery you can get the attributes values lie this:
var id = $(this).attr('data-id');
You can even go further, and remove the "onclick=edit" part. Then use jQuery to susbscribe the click event to all the elements with the required attribute, like this
$(document).ready(function() {
// this happens when all the page has been loaded in the browser (ready)
$('input[data-id]').on('click', function() {
// find the input elements with the "data-id" attr, and, when 'click'ed...
var id = $(this).attr('data-id');
//get the attribute value and do whatever you want with it...
});
});
*NOTE: you can use var id = $(this).data('id'); as an alternative.
This technique is known as "unobtrusive JavaScript". To do this, of course, you need to include jQuery in your page. Please, start using jQuery (or any other library) tha will make things easier for you. if you use it, I'd recommend you to use "namespaced" names for the attributes to avoid collisions. I.e, something like "data-mynamespace-id", using whatever makes sense as your namespace.
Try this:
<input type="button" onclick="edit('#(x.id)');" value="Edit">
Note that if you want to pass variable from your ViewModel to javascript you should use qoutes like this:
<script type="text/javascript">
var x = '#Model[0].x';
</script>
Also you can try declaration of edit function before table.
So in my view I am dynamically creating dropdown lists in a for loop. I use the same name value in unique id values.
#foreach(var item in Model.Items)
{
#Html.DropDownList("Items" Model.GenerateSelectList(item.id), new { id = item.id })
}
In my controller action method for the post I can get the values of the dropdowns like this:
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize]
public ActionResult ClassicLineup(IList<int> items)
{
}
I cannot figure out how to get BOTH the dropdown id and associated value.
Seems like it should be simple but it has me stumped...
Thanks.
On form submit browser sends only the selected value of a dropdown, so there is no bult in mechanism to read the text of selected item, but you can create one for you.
In below code i have created a hidden input which stores the text of current selected item, and is send to the server on form post.
You can create below list in controller or in view (preferred place in controller);
var items= (from item in Model.Items
select new SelectListItem
{
Value= item.DisplayProperty
Text= item.Value
}).toList();
<form action="controller/test">
#*This will create DD*#
#Html.DropDownList("MyDropDownList", items)
#*Hidden input*#
<input type="hidden" id="ddSelectedName" name="ddSelectedName" />
<br>
<input type="submit" value="submit"/>
</form>
Include jQuery in ur code and then add this
<script type="text/javascript">
$('#MyDropDownList').change(function () {
$('#ddSelectedName').val($(this).find(':selected').text());
});
</script>
Controller
public string test(string MyDropDownList, string ddSelectedName)
{
return MyDropDownList+ "--"+ddSelectedName ;
}
I just ended up looping through the forms collection and parsing the dropdown id (form.key) and the dropdown value (form.key.value).
Apparently there is not an easy way to have MVC bind the dropdown values and id to a collection in the controller action parameter.
I have a strongly typed partial view that populates all the Records from Search table.
Now i have a textbox to enter name & a button to filter the records that can match a name.(Like Search page).
Can anybody provide code sample for this scenario?
My Main Page loads particular view based on the radiobutton selection(Search or Inquiry) as below using JQuery:
/* Loading the partial view based on radio button click... */
$(document).ready(function() {
$(':radio').click(function() {
if (this.value == '2') {
$('#ViewAllInquiries').load('/Home/Inquiry', function(html) { $('#ViewAllInquiries')[0].value = html; });
}
else {
$('#ViewAllInquiries').load('/Home/Search', function(html) { $('#ViewAllInquiries')[0].value = html; });
}
});
})
Here is my one of the Partial view ControllerCode:
[HttpGet]
public ActionResult Search()
{
var search = from s in entity.Search
select s; return PartialView(search);
}
Here is the User control Partial view(Search.ascx):
>" %>
<table >
<thead>
<tr>
<th align="left"> </th>
<th align="left"> TX_Id</th>
<th align="left">Name
<%= Html.TextBox("Name")%> <input type="submit" value="Filter" /></th>
<th align="left">Email Address</th>
</tr>
<% foreach (var item in Model)
{ %>
<%= Html.Encode(item.TX_Id) %>
"><%= Html.Encode(item.CustomerMaster.FullName()) %>
<%= Html.Encode(item.CustomerMaster.MS_Id) %>
<% } %>
Thanks for your time.
I do the same thing using an Ajax form. It's really easy. Here's the code I use:
Html:
<div>
<%
using (Ajax.BeginForm("Home", "Search", null,
new AjaxOptions { UpdateTargetId = "Output" },
new { id = "SearchForm" }))
{
%>
<!-- Form Fields -->
<input name="searchField" />
<input type="submit" value="Search" />
<%
}
%>
<div id="Output">
</div>
</div>
Then in the controller you just have:
public PartialViewResult Search(FormCollection form)
{
var model = YourSearchMethod(form["searchField"]);
return PartialView("Search", model);
}
The div with the id "Output" will be updated with your partial view result every time the submit button is clicked. In your case you have two different potential partial views, just submit the radio button value as part of your form and you can switch the output view from within the controller.
Why use FormCollection instead of parameters? I've had some difficult using named parameters with ajax forms, but you can try it and see how it works. It should look something like this instead:
public PartialViewResult Search(string searchField, bool inquiry)
{
if (inquiry)
{
var model = YourInquiryMethod(searchField);
return PartialView("Inquiry", model);
}
else
{
var model = YourSearchMethod(searchField);
return PartialView("Search", model);
}
}
I do the same on one of my sites but have implmented it a little diffently.
I have, in my View the following html;
<div class="EditProductContainer hidden"></div>
I also have the following jQuery;
function editBenefit(objThis) {
var id = $(objThis).parents('.Benefit').attr("id");
$.post("/Home/jQueryGetBenefit", { Id: id },
function(newHTML) {
$('.EditProductContainer').html(newHTML);
});
}
Then in my controller I have;
[AcceptVerbs(HttpVerbs.Post)]
public PartialViewResult jQueryGetBenefit(int Id)
{
Application application = Helpers.CacheHelper.Get();
Benefit thisBenefit = application.findBenefit(Id);
return PartialView("EditBenefit", thisBenefit);
}
I think this is doing what you want but I'm returning a rendered PartialView and replacing the contents of a containing div with the html generated by the partial view.
Hope this is of some help.