Controller:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class ExperimentalController : Controller
{
public ActionResult ReloadTest1()
{
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
return View();
}
public PartialViewResult ReloadTest1Partial()
{
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
return PartialView();
}
}
View:
#{
ViewBag.Title = "ReloadTest1";
string time = this.ViewBag.Time;
ViewData["date"] = time;
ViewBag.TheTitle = "test";
}
<h2>ReloadTest1</h2>
<select id="iSelect" name="iSelect" >
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", null, new ViewDataDictionary { {"vb", ViewBag}});}
</div>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$('#iSelect').on('change', function () {
$("#myPartialViewContainer").load('#(Url.Action("ReloadTest1Partial", "Experimental", null, Request.Url.Scheme))')
})
</script>
Partial View:
#{
var vb = ((dynamic)ViewData["vb"]);
}
<div>
<span>#vb.Time</span>
</div>
What is not working:
Passing the viewbag/viewdata directly from controller to partial view because mvc does not accept that to happen.
What is working:
from the above code you can see that the partial view gets the data ONCE with the Html.RenderPartial method and the viewbag passing down.
the reload does work on change of the selected object in the dropdown
What is needed:
I need to pass data to the partial view when it is reloaded or afterwards, this is mainly a test setup but i finally want to be able to update tables dependant on the select value.
If somone is able to give me a working example please do so.
In your controller you;re using ViewBag to set custom value, but in your view you are working with ViewData as well as referring to a different name (you're setting ViewBag's Time property in controller, but you expect ViewData's vb property in the view).
Change your view to expect model`:
#model MyModel
#{
string time = "";
if (ViewData["Time"] != null)
{
time = ViewData["Time"];
}
}
<div>
<span>#Model.Time</span>
</div>
And change you controller to pass it:
public ActionResult ReloadTest1()
{
var model = new MyModel {Time = DateTime.Now.ToString()};
return View(model);
}
public PartialViewResult ReloadTest1Partial()
{
var model = new MyModel {Time = DateTime.Now.ToString()};
return PartialView(model);
}
And you master view file will look like this:
#model MyModel
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", model);}
</div>
And create your model:
public class MyModel
{
public string Time {get;set;}
}
As a side not, it's always preferable to use a strongly-typed model instead of ViewBag or ViewData as you can get compilation errors and IntelliSense
Final solution:
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
namespace RolloutTool.Controllers
{
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class ExperimentalController : Controller
{
public ActionResult ReloadTest1()
{
var model = new RolloutTool.Models.ExperimentalViewModels.MyModel { Time = DateTime.Now.ToString() };
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
ViewData["Time"] = temp;
return View(model);
}
[HttpPost]
public PartialViewResult ReloadTest1Partial(string test)
{
var model = new RolloutTool.Models.ExperimentalViewModels.MyModel { Time = DateTime.Now.ToString() };
string temp = DateTime.Now.ToString();
ViewBag.Time = temp;
ViewData["Time"] = temp;
return PartialView("_ReloadTest1Partial", model);
}
// GET: Experimental
public ActionResult Experimental()
{
ViewBag.Message = "Your contact page.";
ViewBag.TestValue = 10;
string[] temp = { "alpha", "beta", "gamma", "delta" };
ViewBag.names = temp;
int temp2 = temp.Length;
ViewBag.nameslength = temp2;
return View();
}
}
}
View:
#{
ViewBag.Title = "ReloadTest1";
string time = this.ViewBag.Time;
ViewData["date"] = time;
ViewBag.TheTitle = "test";
}
#model RolloutTool.Models.ExperimentalViewModels.MyModel
<h2>ReloadTest1</h2>
<select class="chosen-select" id="iSelect" name="iSelect">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<div id="myPartialViewContainer">
#{Html.RenderPartial("_ReloadTest1Partial", Model);}
</div>
#Styles.Render(
"~/content/chosen/chosen.css",
"~/content/chosen/prism.css",
"~/content/chosen/style.css",
"~/content/bootstrap.css",
"~/content/Site.css")
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/chosen/chosen.jquery.js"></script>
<script src="~/Scripts/chosen/prism.js"></script>
<script>
var config = {
'.chosen-select': {},
'.chosen-select-deselect': { allow_single_deselect: true },
'.chosen-select-no-single': { disable_search_threshold: 10 },
'.chosen-select-no-results': { no_results_text: 'Oops, nothing found!' },
'.chosen-select-width': { width: "95%" }
}
for (var selector in config) {
$(selector).chosen(config[selector]);
}
</script>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$('#iSelect').on('change', function () {
getPartial();
})
</script>
<script>
function getPartial() {
var tempSelect = document.getElementById("iSelect");
var tempResult = tempSelect.options[tempSelect.selectedIndex].text;
$.ajax({
url: "ReloadTest1Partial",
type: "POST",
data: {'test' = tempResult}, //if you need to post Model data, use this
success: function (result) {
$("#myPartialViewContainer").html(result).find("select").each(function () {
$(this).chosen({});
}
});
}
</script>
#{
string time = "";
string temp = "";
if (ViewData["vb"] != null)
{
temp = "1";
time = ((dynamic)ViewData["vb"]).Time;
}
else if (ViewContext.Controller.ViewBag.Time != null)
{
temp = "2";
time = ViewBag.Time;
}
else if (ViewData["Time"] != null)
{
temp = "3";
time = (string) ViewData["Time"];
}
}
#model RolloutTool.Models.ExperimentalViewModels.MyModel
<div>
<span>#time</span>
<span>#Model.Time</span>
<span>#temp</span>
</div>
<select class="chosen-select"></select>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/chosen/chosen.jquery.js"></script>
<script src="~/Scripts/chosen/prism.js"></script>
This updates the partial view correctly AND reloads the chosen-select dropdowns. (see styles and scripts not working in partial view)
Related
I have a functionality where I append a select html when a button is clicked using jQuery. I already have a select which uses a asp-item tag helper to fill it with my corresponding model. The platform I'm using is asp-net core 2.2 and I'm using a razor page for my page.
My question is how do I edit my jQuery so that when I clicked the button, the asp-item is already loaded into the select?
Here is my jQuery code:
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$(".addselection").append('<div> <select class="form-control" name="[' + (tc) + '].DriverID" asp-for="TripDrivers.DriverID" asp-items="Model.DriverList" > <option value = ""> Select a driver </option></select></div>')
});
and this is my OnGet to load the items
public IActionResult OnGet()
{
DriverList = _context.Drivers.Select(a =>
new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName
}).ToList();
}
This is my first ever question, so please bear with me if there are any grammatical errors or missing information. I'll add them if necessary.
EDIT: Here is the design I'm trying to do.
Once the plus button is clicked. It should add a row of dropdownlist each with the option being loaded from the list on the OnGet method.
ANOTHER EDIT: As per user #itminus instructions, I've created a one sample page and a partial view to apply the code given below.
Here is what my FirstPage.cshtml looks like
#page
#model MasigasigTrackingSystem.Pages.TestingPages.FirstPageModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>FirstPage</title>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script>
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList', {
method: "GET",
data: { tc: tc },
success: function (d) { $(".addselection").append(d); }
});
});
</script>
</head>
<body>
<button id="AddButton" class="btn" type="button">+</button>
#*<select asp-for="Mode" asp-items="Model.DropdownListViewModel.Drivers" class="form-control">
<option value="">Select a driver</option>
</select>*#
<div class="addselection">
<partial name="_SecondPage.cshtml" />
</div>
</body>
</html>
My FirstPageModel
namespace MasigasigTrackingSystem.Pages.TestingPages
{
public class FirstPageModel : PageModel
{
private readonly MasigasigTrackingSystem.Data.ApplicationDBContext _context;
public FirstPageModel(MasigasigTrackingSystem.Data.ApplicationDBContext context)
{
_context = context;
}
[BindProperty]
public Drivers Drivers { get; set; }
public List<SelectListItem> DriverList { get; set; }
[BindProperty]
public DropdownListViewModel DropdownListViewModel { get; set; }
public void OnGet()
{
DriverList = _context.Drivers.Select(a =>
new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName
}).ToList();
DropdownListViewModel = new DropdownListViewModel();
DropdownListViewModel.Drivers = DriverList;
}
public IActionResult OnGetDropdownListAsync(int tc)
{
var list = _context.Drivers.Select(a => new SelectListItem
{
Value = a.ID.ToString(),
Text = a.FullName,
}).ToList(); // or filter by Where( ... tc...).ToList()
return Partial("/Pages/TestingPages/_SecondPage.cshtml", new DropdownListViewModel
{
Drivers = list,
ID = tc,
});
}
}
}
My partial _SecondPage
#using MasigasigTrackingSystem.Models
#model DropdownListViewModel
<div>
<select class="form-control dropdown" name="[#Model.ID].DriverID" asp-items="#Model.Drivers">
<option> Select a driver </option>
</select>
</div>
My DropdownlistViewModel
namespace MasigasigTrackingSystem.Models
{
public class DropdownListViewModel
{
public int ID { get; set; }
public IList<SelectListItem> Drivers { get; set; }
}
}
Here's a demo that gets the partial view dynamically from server.
Create a Handler OnGetDropdownListAsync(int tc) in your PageModel:
public class YourPageModel : PageModel
{
... other handler methods, e.g. OnGet() render the Index
public IActionResult OnGetDropdownListAsync(int tc)
{
var list = _context.Drivers.Select(a =>new SelectListItem{
Value = a.ID.ToString(),
Text = a.FullName,
}).ToList(); // or filter by Where( ... tc...).ToList()
return Partial( "/Pages/Shared/Selection.cshtml" , new DropdownListViewModel{
Drivers = list,
Index = tc,
});
}
}
Here the DropdownListViewModel is a plain ViewModel that holds the data:
public class DropdownListViewModel{
public IList<SelectListItem> Drivers{get;set;}
public int Index {get;set;}
}
Move your original html snippet within jQuery into a new partial view file: /Pages/Shared/Selection.cshtml
#using App.Pages
#model DropdownListViewModel
<div>
<select class="form-control dropdown" name="[#Model.Index].DriverID" asp-items="#Model.Drivers">
<option> Select a driver </option>
</select>
</div>
Finally, change your JavaScript to send an ajax request and update the UI in following way:
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList',{
method:"GET",
data:{ tc: tc },
success:function(d){ $(".addselection").append(d); }
});
});
[Edit]
You are passing currect ViewData to <partial> implicitly, which leads to this type error. You need change it to :
<partial name="/Pages/TestingPages/_SecondPage.cshtml" model="#Model.DropdownListViewModel" />
You're referencing an slim jQuery that doesn't have a ajax. Please change the script to <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>.
You're binding an event for #AddButton before this element has been created. You need wrap the js into a $(document).ready(function(){ .... }. You can also create a manually script after the #AddButton element. Or put the <script> into #section Scripts{} if you're using a default Layout which will make the script take effect after the page has been loaded.
Also you didn't initialize a tc variable.
In short, you need fix the bugs as below:
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function(){
var tc = 0;
$("#AddButton").click(function () {
tc = tc + 1;
$("#totalContacts").val(tc)
$.ajax('?handler=DropdownList', {
method: "GET",
data: { tc: tc },
success: function (d) { $(".addselection").append(d); }
});
});
});
</script>
...
<div class="addselection">
<partial name="/Pages/TestingPages/_SecondPage.cshtml" model="#Model.DropdownListViewModel" />
</div
I apologize I am still fairly new to MVC. I currently have a dropdownlist with some options. What I would like to do is depending on the dropdownlist value that I select then I should be able to render a partial view. I want the partial view to load as soon as the user selects from the dropdownlist.
Also, I am able to render my partial view but it's not returning what I need. When I select from the dropdownlist it does not take the functionID..it just returns all of the items regardless of the functionID.
I want the partial view to render based off the functionID.
Thank you very much. Any help is very much appreciated it.
Main View
#Html.DropDownListFor(m => m.FunctionID, new
SelectList(Model.functionList, "FunctionID", "Name"), "Select
Function", new {#id="id"})
<div id="partialPlaceHolder">
</div>
Partial View
#foreach (var items in Model.itemTypeList)
{
<pre> #items.Definitions</pre>
}
Controller
[HttpGet]
public ActionResult ViewOverview()
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
Words viewModel = new Words();
MetricDefinitions(viewModel);
return View(viewModel);
}
[HttpGet]
public ActionResult GetWords()
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
Words viewModel = new Words()
{
itemTypeList = itemTypeList,
functionList = functionList
};
return PartialView("_ViewWords", viewModel);
}
private void MetricDefinitions(Words model)
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
model.functionList = functionList;
model.itemTypeList = itemTypeList;
}
javascript
$(document).ready(function () {
$('#id').change(function () {
var selectedID = $(this).val();
$.get('/Home/GetWords/' + selectedID, function (data) {
$('#partialPlaceHolder').html(data);
/* little fade in effect */
$('#partialPlaceHolder').fadeIn('fast');
});
});
});
I have added NetFiddle. It works here
Can you try to add selectedItem param into action and use jquery .load() function to get partial result into your target element.
[HttpGet]
public ActionResult GetWords(int selectedItem) // add your selectedVal value in controller
{
.....
}
jquery
// it is going to parse partial view into target div
$("#id").on("change", function(){
var url = '#Url.Action("GetWords", "Home")' + "?selectedItem=" + $(this).val();
$("#partialPlaceHolder").load(url, function(){
console.log("It worked");
$('#partialPlaceHolder').fadeIn('fast');
})
})
I dont know whats wrong.
I follow this link http://www.dotnetcodesg.com/Article/UploadFile/2/286/CRUD%20operation%20using%20Modal%20Popup%20in%20ASP.NET%20MVC%204.aspx because need pretty same thing: CRUD grid with popup for edit.
I do everything inside HomeController and Index.cshtml which generated by VS2013.
I cut from the code the things involved:
Index.cshtml
grid.Column("", header: "Actions",
format: #<text>
#Html.ActionLink("Edit", "EditConstruct", new { id = item.Id, #class = "editDialog" })
<div id="dialog-edit" style="display: none">
Controller
public ActionResult EditConstruct(int id)
{
var data = advConstructRepository.Get(id);
AdvConstructModel model = new AdvConstructModel
{
Id = data.Id,
Description = data.Description,
MaintenanceTime = data.MaintenanceTime,
Location = data.Location,
Height = data.Height,
Width = data.Width,
MonthlyCost = data.MonthlyCost,
AdvConstructType = advConstructRepository.GetAdvConstructType(data.AdvTypeId)
};
ViewBag.IsUpdate = true;
return View("EditConstruct", model);
}
Edit View
#model AdvApplication.Models.AdvConstructModel
#{
Layout = null;
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
#using (Html.BeginForm("UpdateConstruct", "Home", "POST"))
{
#Html.ValidationSummary(true)
ViewBag.IsUpdate = true;
return View("EditConstruct", model);
}
etc...
But when i clicked on Edit action, i receive fields for edit but not in the popup, but on whole screen as a single page.
EditConstruct view was created as partial view.
Please suggest how to fix
It is probably the whole view being sent back, jquery deals in fragments, not whole pages.
Consider this change:
public ActionResult EditConstruct(int id)
{
var data = advConstructRepository.Get(id);
AdvConstructModel model = new AdvConstructModel
{
Id = data.Id,
Description = data.Description,
MaintenanceTime = data.MaintenanceTime,
Location = data.Location,
Height = data.Height,
Width = data.Width,
MonthlyCost = data.MonthlyCost,
AdvConstructType = advConstructRepository.GetAdvConstructType(data.AdvTypeId)
};
ViewBag.IsUpdate = true;
if(Request.IsAjaxRequest())
return PartialView("EditConstruct", model);
return View("EditConstruct", model);
}
I have a two cascading dropdown, when I run the application everything works fine, because the cascade works, but when I get the value of the dropdown only get the value of first dropdown. The second I always get the value of zero.
The ViewModel code:
public class MyViewModel
{
public string SelectedUniversidadId { get; set; }
public string SelectedCiudadId { get; set; }
public IEnumerable<UNIVERSIDAD> Universidades { get; set; }
}
Partial view code:
<script type="text/javascript">
$(function () {
$('#universidad').change(function () {
var selectedUniversidadId = $(this).val();
$.getJSON('#Url.Action("GetCiudadList", "Consultorio", new { Area = "Superusuario", controller = "Consultorio" })', { UniversidadId: selectedUniversidadId }, function (myData) {
var citiesSelect = $('#ciudad');
citiesSelect.empty();
$.each(myData, function (index, itemData) {
citiesSelect.append($('<option/>', {
value: itemData.Value,
text: itemData.Text
}));
});
});
});
});
</script>
#model RolesMVC3.Areas.Superusuario.Models.MyViewModel
<div>
Universidad:
#Html.DropDownListFor(x => x.SelectedUniversidadId, new SelectList(ViewBag.IdUniversidad, "IdUniversidad", "Nombre"), "-- Selecione Universidad --", new { id = "universidad" })
</div>
<div>
Ciudad:
#Html.DropDownListFor(x => x.SelectedCiudadId, Enumerable.Empty<SelectListItem>(), "-- Seleccione Ciudad --", new { id = "ciudad" })
</div>
Controller code:
public ActionResult GetCiudadList(int UniversidadId)
{
decimal idd = (decimal)UniversidadId;
var universidades = (from u in db.UNIVERSIDAD
join s in db.SEDE_UNIVERSIDAD on u.IdUniversidad equals s.IdUniversidad
join c in db.CIUDAD on s.IdCiudadSede equals c.IdCiudad
where u.IdUniversidad == idd
select c).ToList();
var myData = universidades.Select(a => new
{
Text = a.NombreCiudad,
Value = a.IdCiudad.ToString(),
});
return Json(myData, JsonRequestBehavior.AllowGet);
Thanks and blessings
You need a controller action that receives 2 parameters (selected values for the 2 dropdowns). Also, pay attention to the values of the name attributes for the input elements. the name of the parameters need to be the same as the "name" input attribute.
I am trying to use Jeditables (http://www.appelsiini.net/projects/jeditable) in my first castle monorail mvc application
I managed to have the textbox appearing and to the the ajax call, my problem is now that after the ajax call the edited text returs is not changes and i can t get the response after the call
this is my page
<head>
<link href="../../Styles/Main.css" rel="stylesheet" type="text/css" />
<script src="../../JavaScript/jQuery1.4.2.js" type="text/javascript"></script>
<script src="../../JavaScript/EditInLine.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('.editable').editable('/Home/Save', {
id : 'editableId',
name : 'editableText',
type : 'textarea',
cancel : 'Cancel',
submit : 'OK',
indicator : '<img src="img/indicator.gif">',
tooltip : 'Click to edit...',
width : '200',
style : 'display: inline',
callbac : function(value, settings) {
alert(value);
return value;
}
});
});
</script>
</head>
<body>
<label id='1' class='editable '>Some text</label>
</body>
</html>
and this my controller
using Castle.MonoRail.Framework;
using System;
using EditInLine.Model.Interfaces;
using EditInLine.Model;
namespace EditInLine.Controllers
{
[Layout("Default"), Rescue("Default")]
public class HomeController : SmartDispatcherController
{
private EditableElement editableElement;
private EditableElement EditableElement
{
get
{
if (Session["EditableElement"] == null)
{
Session["EditableElement"] = new EditableElement { Id = 1, Text = "Some text", CssClass = "editable" };
}
return (EditableElement)Session["EditableElement"];
}
}
public void Index()
{
PropertyBag["IsAdmin"] = true;
PropertyBag["element"] = EditableElement;
}
public void Save()
{
var elementId = Convert.ToInt32(Request.Form["editableId"]);
var text = Request.Form["editableText"];
var element = new EditableElement { Id = elementId, CssClass = "editable", Text = text };
Session["EditableElement"] = element;
}
}
}
thanks for you help
The problem with Save() was that you did not return a string to the browser. Easily fixed with RenderText() call. You should also be using parameter binding instead of messing with Request.Form:
public void Save(int editableId, string editableText)
{
var element = new EditableElement { Id = editableId, CssClass = "editable", Text = editableText};
Session["EditableElement"] = element;
RenderText(editableText);
}
I found the solution
public void Save()
{
var elementId = Convert.ToInt32(Request.Form["editableId"]);
var text = Request.Form["editableText"];
var element = new EditableElement { Id = elementId, CssClass = "editable", Text = text };
Session["EditableElement"] = element;
Response.Write(text);
CancelView();
}